简体   繁体   English

如何在 MDI MFC C++ windows 应用程序中动态更改 CFormView WIDTH 或 HEIGHT?

[英]How to change dynamically CFormView WIDTH or HEIGHT in MDI MFC C++ windows application?

In 1997, I have used C++ to create an MDI MFC program. 1997 年,我使用 C++ 创建了一个 MDI MFC 程序。

I have created a Class named XFormFiew that extends MFC CFormView class.我创建了一个名为 XFormFiew 的类,它扩展了 MFC CFormView 类。

In OnInitialUpdate() event method, I have written some codes to modify automatically the zooming of the view.OnInitialUpdate()事件方法中,我编写了一些代码来自动修改视图的缩放。

In the past, the majority of screen resolution are 800x600, but now the resolution is higher.过去,大多数屏幕分辨率都是800x600,但现在分辨率更高了。 In zooming automatically in XFormView , I avoid to made some modifications in all my views.XFormView自动缩放时,我避免对所有视图进行一些修改。

The zooming code modify Left and Bottom but also Width and Height of each CWnd contained in active CFormView缩放代码修改 Left 和 Bottom 以及活动CFormView包含的每个CWnd宽度和高度

The code is the following代码如下

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);
    }

The code work well but for some views, the vertical and horizontal scrollbar are missing.该代码运行良好,但对于某些视图,缺少垂直和水平滚动条。

The Window is always loaded MAXIMIZED.窗口始终加载为 MAXIMIZED。 If I unmaximize Window, the scrollbars are always missing.如果我取消最大化窗口,滚动条总是丢失。

If I reduce WIDTH or HEIGHT the scrollbar is displayed WHEN width or height reaches what has been defined in RC Resource file.如果我减小 WIDTH 或 HEIGHT,当宽度或高度达到 RC 资源文件中定义的值时,将显示滚动条。

Example:例子:

IDD_OVFORM DIALOGEX 0, 0, 370, 297

where 370 is the width of Form and 297 is height.其中 370 是 Form 的宽度,297 是高度。

If I reduce Child Window width, nothing happens until width is reduced to 370. At this moment an horizontal scrollbar is automatically displayed.如果我减小子窗口的宽度,则在宽度减小到 370 之前不会发生任何事情。此时会自动显示水平滚动条。

My problem is how to change dynamically (not in RC file) the width and height of IDD_OVFORM to correspond to zoom level so that horizontal and vertical scrollbar are displayed correctly ?我的问题是如何动态更改(不在 RC 文件中)IDD_OVFORM 的宽度和高度以对应缩放级别,以便正确显示水平和垂直滚动条?

I have already try to change these properties in OnInitialUpdate() method but nothing is working.我已经尝试在 OnInitialUpdate() 方法中更改这些属性,但没有任何效果。

If I change Width and Height in RC Resource FILE, the zoom work correctly for a specific zoom level (but not for all zoom level).如果我在 RC Resource FILE 中更改 Width 和 Height,缩放会在特定缩放级别(但不是所有缩放级别)下正常工作。

On Internet, I find a some solutions about removing Scrollbars but not about zooming and Scrollbars missing using MDI MFC Form.在 Internet 上,我找到了一些有关删除滚动条的解决方案,但没有找到有关使用 MDI MFC 表单进行缩放和缺少滚动条的解决方案。

Is there somebody that has already found a solution to this problem ?是否有人已经找到了解决此问题的方法?

2019-02-12: thanks to Barmak Shemirani for his solution (OPTION 3) that works perfectly. 2019-02-12:感谢 Barmak Shemirani 的完美解决方案(选项 3)。

Call SetScrollSizes to show the scrollbars at specific sizes:调用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());

But this is not the right method in general.但这通常不是正确的方法。

Option 1:选项1:

You can just go to resource editor, select the dialog, select dialog's properties, and change the dialog's default font size.您只需转到资源编辑器,选择对话框,选择对话框的属性,然后更改对话框的默认字体大小即可。 Increase the font size to 9 or higher, this will automatically make the dialog and its controls bigger, as well as using larger font.将字体大小增加到 9 或更大,这将自动使对话框及其控件更大,并使用更大的字体。

Option 2:选项 2:

In dialog's properties, you will also see a section called "Dynamic Layout".在对话框的属性中,您还将看到一个名为“动态布局”的部分。 This lets you zoom the controls on resize, or move them up/down and left/right.这使您可以在调整大小时缩放控件,或向上/向下和向左/向右移动它们。

Option 3:选项 3:

Change the font in dialog template during run time.在运行时更改对话框模板中的字体。 To do so, you must override CFormView::Create , which in turn calls CreateDlg .为此,您必须覆盖CFormView::Create ,后者又调用CreateDlg These function names have to be declared exactly as below.这些函数名称必须完全如下声明。

Note that the font in dialog template can be changed only once, before the dialog is load.请注意,对话框模板中的字体只能在加载对话框之前更改一次。

Example for Visual Studio 2017 (this code may not be compatible with older MFC versions) Visual Studio 2017 示例(此代码可能与旧 MFC 版本不兼容)

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;
}

and class definition in XFormView.h MUST contains following lines 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);

The OnCreate declaration is absolutely necessary. OnCreate声明是绝对必要的。

Without this declaration, nothing happens !!!没有这个声明,什么都不会发生!!!

OnCreate is only declared in include file but is not defined in CPP file. OnCreate仅在包含文件中声明,但未在 CPP 文件中定义。

Maybe you manually need to call EnableScrollBars for each scroll bar after determining whether it is needed.也许你在确定是否需要之后,需要手动为每个滚动条调用EnableScrollBars

You would probably need to call SetScrollInfo then to setup total size.您可能需要调用SetScrollInfo然后设置总大小。

Both calls need to be done on the parent window of the CFormView which should be CChildFrame .这两个调用都需要在CFormView的父窗口上完成,它应该是CChildFrame

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM