当框架窗口(CMainFrame)的大小改变时,视图窗口(CMyAppView)的大小也跟着变?MFC是怎样做到的?     

解决方案 »

  1.   

    lz可以去看看MFC的源码,看看WM_SIZE里,框架类做了什么处理视图是附载在创建窗口之上的
      

  2.   

    阅读下面的代码,注意长注释条void CFrameWnd::OnSize(UINT nType, int cx, int cy)
    {
    CWnd::OnSize(nType, cx, cy);    // important for MDI Children
    if (nType != SIZE_MINIMIZED)
    RecalcLayout();///////////////
    }void CFrameWnd::RecalcLayout(BOOL bNotify)
    {
    if (m_bInRecalcLayout)
    return; m_bInRecalcLayout = TRUE;
    // clear idle flags for recalc layout if called elsewhere
    if (m_nIdleFlags & idleNotify)
    bNotify = TRUE;
    m_nIdleFlags &= ~(idleLayout|idleNotify);#ifndef _AFX_NO_OLE_SUPPORT
    // call the layout hook -- OLE support uses this hook
    if (bNotify && m_pNotifyHook != NULL)
    m_pNotifyHook->OnRecalcLayout();
    #endif // reposition all the child windows (regardless of ID)
    if (GetStyle() & FWS_SNAPTOBARS)
    {
    CRect rect(0, 0, 32767, 32767);
    RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
    &rect, &rect, FALSE);
    RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra,
    &m_rectBorder, &rect, TRUE);
    CalcWindowRect(&rect);
    SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
    SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
    }
    else
    RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &m_rectBorder);//////////////
    m_bInRecalcLayout = FALSE;
    }void CWnd::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver,
    UINT nFlags, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch)
    {
    ASSERT(nFlags == 0 || nFlags == reposQuery || nFlags == reposExtra); // walk kids in order, control bars get the resize notification
    //   which allow them to shrink the client area
    // remaining size goes to the 'nIDLeftOver' pane
    // NOTE: nIDFirst->nIDLast are usually 0->0xffff AFX_SIZEPARENTPARAMS layout;
    HWND hWndLeftOver = NULL; layout.bStretch = bStretch;
    layout.sizeTotal.cx = layout.sizeTotal.cy = 0;
    if (lpRectClient != NULL)
    layout.rect = *lpRectClient;    // starting rect comes from parameter
    else
    GetClientRect(&layout.rect);    // starting rect comes from client rect if (nFlags != reposQuery)
    layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess
    else
    layout.hDWP = NULL; // not actually doing layout for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
    hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
    {
    UINT nIDC = _AfxGetDlgCtrlID(hWndChild);
    CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);
    if (nIDC == nIDLeftOver)
    hWndLeftOver = hWndChild;
    else if (nIDC >= nIDFirst && nIDC <= nIDLast && pWnd != NULL)
    ::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);
    } // if just getting the available rectangle, return it now...
    if (nFlags == reposQuery)
    {
    ASSERT(lpRectParam != NULL);
    if (bStretch)
    ::CopyRect(lpRectParam, &layout.rect);
    else
    {
    lpRectParam->left = lpRectParam->top = 0;
    lpRectParam->right = layout.sizeTotal.cx;
    lpRectParam->bottom = layout.sizeTotal.cy;
    }
    return;
    } // the rest is the client size of the left-over pane
    if (nIDLeftOver != 0 && hWndLeftOver != NULL)
    {
    CWnd* pLeftOver = CWnd::FromHandle(hWndLeftOver);
    // allow extra space as specified by lpRectBorder
    if (nFlags == reposExtra)
    {
    ASSERT(lpRectParam != NULL);
    layout.rect.left += lpRectParam->left;
    layout.rect.top += lpRectParam->top;
    layout.rect.right -= lpRectParam->right;
    layout.rect.bottom -= lpRectParam->bottom;
    }
    // reposition the window
    pLeftOver->CalcWindowRect(&layout.rect);
    AfxRepositionWindow(&layout, hWndLeftOver, &layout.rect);///////////
    } // move and resize all the windows at once!
    if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
    TRACE0("Warning: DeferWindowPos failed - low system resources.\n");
    }void AFXAPI AfxRepositionWindow(AFX_SIZEPARENTPARAMS* lpLayout,
    HWND hWnd, LPCRECT lpRect)
    {
    ASSERT(hWnd != NULL);
    ASSERT(lpRect != NULL);
    HWND hWndParent = ::GetParent(hWnd);
    ASSERT(hWndParent != NULL); if (lpLayout != NULL && lpLayout->hDWP == NULL)
    return; // first check if the new rectangle is the same as the current
    CRect rectOld;
    ::GetWindowRect(hWnd, rectOld);
    ::ScreenToClient(hWndParent, &rectOld.TopLeft());
    ::ScreenToClient(hWndParent, &rectOld.BottomRight());
    if (::EqualRect(rectOld, lpRect))
    return;     // nothing to do        ////////////////////////////////////////////////////////////
    // try to use DeferWindowPos for speed, otherwise use SetWindowPos
    if (lpLayout != NULL)
    {
    lpLayout->hDWP = ::DeferWindowPos(lpLayout->hDWP, hWnd, NULL,
    lpRect->left, lpRect->top,  lpRect->right - lpRect->left,
    lpRect->bottom - lpRect->top, SWP_NOACTIVATE|SWP_NOZORDER);
    }
    else
    {
    ::SetWindowPos(hWnd, NULL, lpRect->left, lpRect->top,
    lpRect->right - lpRect->left, lpRect->bottom - lpRect->top,
    SWP_NOACTIVATE|SWP_NOZORDER);
    }
    }