How to retrieve the size and position of the initial document of the MDI interface of an MFC application?

Luigi Tofano 20 Reputation points
2025-05-12T22:26:33.08+00:00

https://1drv.ms/u/c/506e10ab962c3b92/EdScY7Cq2RdOgKdPdjCBTecB_WZLBYTT1GtuvO5klbFXbg?e=Su7LFP

Above should be a public link to the project.

Screenshot 2025-05-18 114600

At this point there is a dimensioning problem with the overlay window. So far I would like to cover just the client area of the child window. How can that be done?

Developer technologies | C++
{count} votes

2 answers

Sort by: Most helpful
  1. Sheng Jiang 蒋晟 206 Reputation points
    2025-05-17T18:11:35.46+00:00

    SetWindowPos takes client coordinates (relative to parent window), not screen coordinates. So does CWnd::CreateEx.

    GetDlgItem(AFX_IDW_PANE_FIRST) on an MDI main Frame returns its m_wndClientArea, in which you can drag child frames around. It is not an MDI child.

    GetClientRect returns the client area's location relative to the window itself. For m_wndClientArea and views. it is basically the window itself minus borders.

    I see you handled OnMDIActivate (good) but I don't see how you handled moving/resizing of the child frame/splitter.


  2. Luigi Tofano 20 Reputation points
    2025-05-19T05:20:45.5+00:00
    
    void CChildFrame::OnSize(UINT nType, int cx, int cy)
    {
        CMDIChildWndEx::OnSize(nType, cx, cy);
        // Get the active view
        CView* pView = GetActiveView();
        if (pView)
        {
            // Try to cast to your specific view class
            CMFCMDIOverlayWndExample002View* pMyView = DYNAMIC_DOWNCAST(CMFCMDIOverlayWndExample002View, pView);
            if (pMyView)
            {
                // Get the main frame window
                CMainFrame* pMainFrame = DYNAMIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
                if (pMainFrame)
                {
                    pMainFrame->PrintActiveViewClientRect();
                }
            }
        }
    }
    void CChildFrame::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
    {
        CMDIChildWndEx::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
        if (bActivate)
        {
            // Get the active view
            CView* pView = GetActiveView();
            if (pView)
            {
                // Try to cast to your specific view class
                CMFCMDIOverlayWndExample002View* pMyView = DYNAMIC_DOWNCAST(CMFCMDIOverlayWndExample002View, pView);
                if (pMyView)
                {
                    // Get the main frame window
                    CMainFrame* pMainFrame = DYNAMIC_DOWNCAST(CMainFrame, AfxGetMainWnd());
                    if (pMainFrame)
                    {
                        pMainFrame->PrintActiveViewClientRect();
                    }
                }
            }
        }
    }
    
    
    void CMainFrame::CreateOrUpdateOverlayOverActiveView()
    {
    	CMDIChildWnd* pChild = MDIGetActive();
    	if (!pChild) return;
    	CView* pView = pChild->GetActiveView();
    	if (!pView) return;
    	CMFCMDIOverlayWndExample002View* pMyView = DYNAMIC_DOWNCAST(CMFCMDIOverlayWndExample002View, pView);
    	if (!pMyView) return;
    	CRect clientRect = pMyView->GetClientRectOfView();
    	CPoint topLeft = clientRect.TopLeft();
    	CPoint bottomRight = clientRect.BottomRight();
    	int width = clientRect.Width();
    	int height = clientRect.Height();
    	pMyView->ClientToScreen(&topLeft);
    	pMyView->ClientToScreen(&bottomRight);
    	RECT screenRect = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y };
    	if (!::IsWindow(m_hOverlayWnd))
    	{
    		static bool bClassRegistered = false;
    		if (!bClassRegistered)
    		{
    			WNDCLASS wc = { 0 };
    			wc.lpfnWndProc = OverlayWndProc; // Static WNDPROC defined above
    			wc.hInstance = AfxGetInstanceHandle();
    			wc.lpszClassName = _T("OverlayWindowClass");
    			wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
    			RegisterClass(&wc);
    			bClassRegistered = true;
    		}
    		m_hOverlayWnd = ::CreateWindowEx(
    			WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
    			_T("OverlayWindowClass"),
    			_T("Overlay"),
    			WS_POPUP,
    			screenRect.left, screenRect.top,
    			screenRect.right, screenRect.bottom,
    			nullptr, nullptr, AfxGetInstanceHandle(), nullptr);
    		if (!m_hOverlayWnd)
    		{
    			TRACE("Overlay creation failed, Error: %d\n", ::GetLastError());
    			return;
    		}
    		::SetLayeredWindowAttributes(m_hOverlayWnd, 0, 128, LWA_ALPHA);
    		::ShowWindow(m_hOverlayWnd, SW_SHOWNOACTIVATE);
    		::UpdateWindow(m_hOverlayWnd);
    	}
    	::SetWindowPos(
    		m_hOverlayWnd, HWND_TOPMOST,
    		screenRect.left, screenRect.top,
    		width, height,
    		SWP_NOACTIVATE | SWP_SHOWWINDOW);
    }
    void CMainFrame::PrintActiveViewClientRect()
    {
    	CreateOrUpdateOverlayOverActiveView();
    	// Get the active MDI child window
    	CMDIChildWnd* pChild = MDIGetActive();
    	if (!pChild)
    		return;
    	// Get the active view
    	CView* pView = pChild->GetActiveView();
    	if (!pView)
    		return;
    	// Try to cast to your specific view class
    	CMFCMDIOverlayWndExample002View* pMyView = DYNAMIC_DOWNCAST(CMFCMDIOverlayWndExample002View, pView);
    	if (!pMyView)
    		return;
    	// Get the client rectangle using your new function
    	CRect rect = pMyView->GetClientRectOfView();
    	// Print to the console
    	std::cout << "Active View Client Rect: left=" << rect.left
    		<< ", top=" << rect.top
    		<< ", right=" << rect.right
    		<< ", bottom=" << rect.bottom
    		<< ", width=" << rect.Width()
    		<< ", height=" << rect.Height()
    		<< std::endl;
    }
    
    

    If this relative dogma is followed there should be a correctly sized overlay window showing up.
    Screenshot 2025-05-18 222003

    This is what the resultant overlay window should look like.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.