在众多MFC实现可调整大小对话框的方案中,WTL提供了自己的解决方案,使得开发者只需要学习一种类和一种指定调整大小的方式。本文将概述WTL的调整大小支持,并提供一个示例程序来展示一些特性。
应该已经熟悉WTL以及如何安装它。如果需要帮助,WTL部分有相关文章。
和其他许多WTL特性一样,首先需要将CDialogResize添加到对话框类的继承列表中。如果使用WTL AppWizard创建一个基于对话框的应用程序,会在此处添加如下代码:
class CMainDlg : public CAxDialogImpl, public CDialogResize {
//...
};
CDialogResize在atlframe.h中声明,所以如果包含文件中还没有它,请添加该头文件。
接下来,在对话框的OnInitDialog处理程序中初始化CDialogResize代码:
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
// 初始化CDialogResize代码
DlgResize_Init();
...
}
DlgResize_Init()有一些可选参数,稍后会介绍。
然后,在对话框的消息映射中添加一个条目,将调整大小的消息传递给CDialogResize:
BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
...
CHAIN_MSG_MAP(CDialogResize)
END_MSG_MAP()
最后,在对话框类中添加一个新的映射,列出对话框中哪些控件将被调整大小:
class CMainDlg : public CAxDialogImpl, public CDialogResize {
...
public:
BEGIN_DLGRESIZE_MAP(CMainDlg)
END_DLGRESIZE_MAP()
...
};
将在“设置调整大小映射”部分描述如何填写这个映射。
通过调用DlgResize_Init()来初始化CDialogResize。它的原型是:
void CDialogResize::DlgResize_Init(
bool bAddGripper = true,
bool bUseMinTrackSize = true,
DWORD dwForceStyle = WS_THICKFRAME | WS_CLIPCHILDREN);
参数如下:
对话框调整大小映射告诉CDialogResize哪些控件需要移动或调整大小。一个条目看起来像这样:
DLGRESIZE_CONTROL(ControlID, Flags)
ControlID是对话框控件的ID。可能的标志及其含义如下:
注意不能在同一个维度上移动和调整大小一个控件。如果指定了DLSZ_MOVE_X和DLSZ_SIZE_X,大小标志将被忽略。
也可以将控件分组,使它们彼此成比例地移动和调整大小。稍后将讨论这个话题。
本文附带的示例项目是一个简单的基于对话框的应用程序,它作为一个浏览器(使用WebBrowser ActiveX控件)来工作。下面列出了控件ID;稍后讨论移动和调整这些控件大小时,应该参考这个图表。
控件将根据以下规则移动和调整大小:
浏览器的OnInitDialog()函数像这样初始化CDialogResize:
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
// 初始化CDialogResize代码
DlgResize_Init();
...
}
这使用了DlgResize_Init()的默认参数,结果是一个大小框被添加。此外,对话框不能被调整到比其初始大小更小。这是对话框启动时的样子:
这是调整大小映射,它列出了控件的移动和调整大小行为。注意新的宏BEGIN_DLGRESIZE_GROUP()和END_DLGRESIZE_GROUP() - 它们将四个浏览器控件按钮放入一个调整大小组中。
BEGIN_DLGRESIZE_MAP(CMainDlg)
// Location edit box
DLGRESIZE_CONTROL(IDC_URL, DLSZ_SIZE_X)
// Go, Exit, About buttons
DLGRESIZE_CONTROL(IDC_GO, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_EXIT, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(ID_APP_ABOUT, DLSZ_MOVE_X)
// IE control buttons
BEGIN_DLGRESIZE_GROUP()
DLGRESIZE_CONTROL(IDC_BACK, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_FORWARD, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_STOP, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_REFRESH, DLSZ_SIZE_X)
END_DLGRESIZE_GROUP()
// WebBrowser control
DLGRESIZE_CONTROL(IDC_BROWSER, DLSZ_SIZE_X|DLSZ_SIZE_Y)
END_DLGRESIZE_MAP()
这是调整大小后的对话框:
注意编辑框变宽了,浏览器控件变宽变高了。四个分组按钮的行为有点难以用语言表达,WTL代码由于注释很少,提供的指导有限。但基本思想是:想象一个包围所有四个按钮的边界矩形。那个矩形像任何其他控件一样调整大小,所有按钮按比例调整大小,以便它们保持在边界矩形内。如果按钮要被移动,而不是调整大小,它们会被定位,以便始终保持均匀间隔。注意,一个组中的所有控件应该有相同的DLSZ_*标志,以产生有意义的行为。
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) {
// ...
CMainDlg dlgMain;
int nRet = dlgMain.DoModal();
_Module.Term();
::CoUninitialize();
return nRet;
}
int nRet;
{
CMainDlg dlgMain;
nRet = dlgMain.DoModal();
}