[英]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.