代码之家  ›  专栏  ›  技术社区  ›  schlebe

如何动态改变MDI MFC C++ Windows应用程序中的窗体视图宽度或高度?

  •  2
  • schlebe  · 技术社区  · 5 年前

    在1997,我用C++来创建一个MDI MFC程序。

    我创建了一个名为xformView的类,它扩展了MFC CFormView类。

    在里面 OnInitialUpdate()

    过去,大多数屏幕分辨率为800x600,但现在分辨率更高。自动放大 XFormView

    缩放代码可以修改左侧和底部,还可以修改每个区域的宽度和高度 CWnd CFormView

    代码如下

    void XFormView::OnInitialUpdate()
        {
        CFormView::OnInitialUpdate();
    
        pLogFont = new LOGFONT;
        CFont* pDialogFont = GetFont();
        pDialogFont->GetObject(sizeof(LOGFONT),pLogFont);
        pLogFont->lfHeight = MulDiv(pLogFont->lfHeight, Config.GetDstH(), Config.GetSrcH());
        pLogFont->lfWeight = FW_NORMAL;
    
        pFont = new CFont;
        pFont->CreateFontIndirect(pLogFont);
        SetFont(pFont);
    
        CWnd* pWnd;
        pWnd = GetWindow(GW_CHILD);
        while (pWnd != NULL)
            {
            ZoomWnd(pWnd);
            pWnd = pWnd->GetWindow(GW_HWNDNEXT);
            }
    
        // TRY to modify WIDTH and HEIGTH of CFormView    
        ZoomWnd(this);
        }        
    
    void XFormView::ZoomWnd(CWnd* pWnd)
        {
        CRect rect;
        pWnd->GetWindowRect(&rect);
        ScreenToClient(&rect);
        rect.left   = (int)((long)rect.left   * Config.GetDstH() / Config.GetSrcH());
        rect.top    = (int)((long)rect.top    * Config.GetDstV() / Config.GetSrcV());
        rect.right  = (int)((long)rect.right  * Config.GetDstH() / Config.GetSrcH());
        rect.bottom = (int)((long)rect.bottom * Config.GetDstV() / Config.GetSrcV());
    
        pWnd->MoveWindow(&rect);
        pWnd->SetFont(pFont);
        }
    

    代码运行良好,但对于某些视图,缺少垂直和水平滚动条。

    窗口总是最大化加载。如果我不最大化窗口,滚动条总是丢失。

    如果减小宽度或高度,当宽度或高度达到RC资源文件中定义的值时,将显示滚动条。

    例子:

    IDD_OVFORM DIALOGEX 0, 0, 370, 297
    

    若我减小子窗口的宽度,在宽度减小到370之前不会发生任何事情。此时会自动显示一个水平滚动条。

    我的问题是如何动态地(而不是在RC文件中)更改IDD_OVFORM的宽度和高度以对应缩放级别,从而正确显示水平和垂直滚动条?

    我已经尝试在OnInitialUpdate()方法中更改这些属性,但没有任何效果。

    在互联网上,我找到了一些关于删除滚动条的解决方案,但没有关于使用MDI MFC表单缩放和滚动条丢失的解决方案。

    2019年2月12日:感谢Barmak Shemirani提出的完美解决方案(方案3)。

    2 回复  |  直到 5 年前
        1
  •  1
  •   schlebe    5 年前

    SetScrollSizes 要以特定大小显示滚动条,请执行以下操作:

    CRect rect;
    GetClientRect(rect);
    
    //this multiplication is to make sure the scrollbar is visible
    //remove it in actual code.
    rect.right *= 2;
    rect.bottom *= 2;
    
    SetScrollSizes(MM_TEXT, rect.Size());
    

    但总的来说,这不是正确的方法。

    备选案文1:

    备选案文2:

    在对话框的属性中,您还将看到一个名为“动态布局”的部分。这使您可以在调整控件大小时缩放控件,或上/下和左/右移动控件。

    备选案文3:

    CFormView::Create ,而 CreateDlg . 这些函数名必须完全按照以下方式声明。

    请注意,在加载对话框之前,对话框模板中的字体只能更改一次。

    BOOL XFormView::CreateDlg(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
    {
        CDialogTemplate dlt;
        if(dlt.Load(lpszTemplateName)))
        {
            // set your own font
            dlt.SetFont(L"Arial", 20);
    
            HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
    
            LPCDLGTEMPLATE dlgtemplate = (LPCDLGTEMPLATE)GlobalLock(dlt.m_hTemplate);
    
            // create a modeless dialog
            BOOL bSuccess = CreateDlgIndirect(dlgtemplate, pParentWnd, hInst);
    
            GlobalUnlock(dlt.m_hTemplate);
            return bSuccess;
        }
    
        return CFormView::CreateDlg(lpszTemplateName, pParentWnd);
    }
    
    BOOL XFormView::Create
        ( LPCTSTR lpszClassName
        , LPCTSTR lpszWindowName
        , DWORD dwRequestedStyle
        , const RECT& rect
        , CWnd* pParentWnd
        , UINT nID
        , CCreateContext* pContext
        );
    {
        ASSERT(pParentWnd != NULL);
        ASSERT(m_lpszTemplateName != NULL);
    
        m_pCreateContext = pContext;    // save state for later OnCreate
    
        // call PreCreateWindow to get prefered extended style
        CREATESTRUCT cs; 
        memset(&cs, 0, sizeof(CREATESTRUCT));
        if(dwRequestedStyle == 0)
            dwRequestedStyle = AFX_WS_DEFAULT_VIEW;
        cs.style = dwRequestedStyle;
        if(!PreCreateWindow(cs))
            return FALSE;
    
        // create a modeless dialog
        if(!CreateDlg(m_lpszTemplateName, pParentWnd))
            return FALSE;
    
        m_pCreateContext = NULL;
    
        ModifyStyle(WS_BORDER | WS_CAPTION, cs.style & (WS_BORDER | WS_CAPTION));
        ModifyStyleEx(WS_EX_CLIENTEDGE, cs.dwExStyle & WS_EX_CLIENTEDGE);
    
        SetDlgCtrlID(nID);
    
        CRect rectTemplate;
        GetWindowRect(rectTemplate);
        SetScrollSizes(MM_TEXT, rectTemplate.Size());
    
        // initialize controls etc
        if(!ExecuteDlgInit(m_lpszTemplateName))
            return FALSE;
    
        // force the size requested
        SetWindowPos(NULL, rect.left, rect.top,
            rect.right - rect.left, rect.bottom - rect.top,
            SWP_NOZORDER | SWP_NOACTIVATE);
    
        // make visible if requested
        if(dwRequestedStyle & WS_VISIBLE)
            ShowWindow(SW_NORMAL);
    
        return TRUE;
    }
    

    XFormView.h中的类定义必须包含以下行

    protected:
    
        BOOL Create
            ( LPCTSTR lpszClassName
            , LPCTSTR lpszWindowName
            , DWORD dwRequestedStyle
            , const RECT& rect
            , CWnd* pParentWnd
            , UINT nID
            , CCreateContext* pContext
            );
    
        BOOL CreateDlg(LPCTSTR lpszTemplateName, CWnd* pParentWnd);
    
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    

    这个 OnCreate

    一次创建

        2
  •  0
  •   Damir Valiulin    5 年前

    也许你需要手动打电话 EnableScrollBars 对于每个滚动条,在确定是否需要它之后。

    你可能需要打电话 SetScrollInfo 然后设置总大小。

    CFormView 应该是哪一个 CChildFrame