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

问题描述 投票:2回答:2

1997年,我使用C ++创建了一个MDI MFC程序。

我创建了一个名为XFormFiew的类,它扩展了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);
    }

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

窗口始终加载MAXIMIZED。如果我取消最大化Window,则滚动条总是丢失。

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

例:

IDD_OVFORM DIALOGEX 0, 0, 370, 297

其中370是Form的宽度,297是height。

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

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

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

如果我在RC资源文件中更改宽度和高度,则缩放可以针对特定缩放级别正常工作(但不适用于所有缩放级别)。

在Internet上,我找到了一些关于删除Scrollbars的解决方案,但没有找到关于使用MDI MFC Form丢失缩放和Scrollbars的解决方案。

是否有人已经找到了解决这个问题的方法?

2019-02-12:感谢Barmak Shemirani的解决方案(选项3)完美无缺。

c++ mfc scrollbar zooming
2个回答
1
投票

调用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:

您可以转到资源编辑器,选择对话框,选择对话框的属性,然后更改对话框的默认字体大小。将字体大小增加到9或更高,这将自动使对话框及其控件更大,以及使用更大的字体。

选项2:

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

选项3:

在运行时更改对话框模板中的字体。为此,您必须覆盖CFormView::Create,后者又调用CreateDlg。必须完全按照以下方式声明这些函数名称。

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

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

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声明是绝对必要的。

没有这个声明,没有任何反应!

OnCreate仅在包含文件中声明,但未在CPP文件中定义。


0
投票

也许你手动需要在确定是否需要后为每个滚动条调用EnableScrollBars

您可能需要调用SetScrollInfo然后设置总大小。

两个调用都需要在CFormView的父窗口上完成,该窗口应该是CChildFrame

© www.soinside.com 2019 - 2024. All rights reserved.