对话框模板RegexTest
2010-07-11 20:44:51 来源:WEB开发网一旦你填充完指定的DLGITEMTEMPLATE 数据,便可如法炮制下一个对话框控件,直到完成所有的控件。接着确保 DLGTEMPLATE::cdit 指定正确的控件总数。为了简化建立对话框模板的过程(使之尽量少出错)。我写了一个辅助类,CDlgTemplateBuilder。CStringDialog 用这个类可以一步到位建立对话框:
// in CStringDialog::Init
CDlgTemplateBuilder& dtb = m_dtb;
DLGTEMPLATE* pTempl = dtb.Begin(...);
dtb.AddItem(...);
dtb.AddItem(...);
dtb.AddItem(...);
InitModalIndirect(pTempl, ...);
我已将细节模糊而突出主要思路:调用一次 Begin,然后针对每个控件调用一次 AddItem。CDlgTemplateBuilder::Begin 生成 DLGTEMPLATE 并且每次调用AddItem 生成另一个 DLGITEMTEMPLATE。CDlgTemplateBuilder 在自己的内存缓冲里生成模板并在每次添加控件时自动增加 DLGTEMPLATE::cdit(控件项数目)。CDlgTemplateBuilder 具备辅助函数 AlignDWORD和AddText 以确保数据对齐和实现正确的字符串转换。有关细节自己下载源代码细细琢磨吧。
我前面说过对话框使用对话框单位,而非像素。DLGTEMPLATE和DLGITEMTEMPLATE 两个都包含 x,y,cx h和 cy 成员来指定对话框或控件项的位置和大小。这些值都是对话框单位。每个水平方向的对话框单位是四分之一的基本单位,而每个垂直方向的对话框单位是八分之一的基本单位。一个基本单位是对话框中一个字符宽度和高度的平均值,并且依赖于对话框的字体。是不是很痛苦啊!没错,但凭心而论,这个想法是值得赞誉的:对话框单位使你的对话框外观独立于其字体。所以不管你用大字体也好,小字体也好,所有控件的相对位置是不会变的,一切都显示正常。Windows 有一个特别的函数叫做 MapDialogRect,用来将对话框单位转换为像素;令人惊讶的是却没有反向转换函数,而这正是生成模板所需要的——但你可以用如下公式:
CSize base = ::GetDialogBaseUnits();
xDlg = MulDiv(xPixel, 4, base.cx);
yDlg = MulDiv(yPixel, 8, base.cy);
对于 CStringDialog 来说,我懒得去做这些事情,而是试验性找到正确的值显示出如图 Figure 1 所示的对话框。更复杂的实现得检查提示串的长度,或允许调用这指定尺寸。如果处理这些对话框单位让你头痛,那么你就创建大小和位置都是0 的控件得了,然后实现 OnSize 处理例程将控件移到适合的像素位置。你的对话框得从 OnInitDialog 向自身发送 WM_SIZE 消息以确保第一次显示时控件被正确定位。
最后,我是如何让 CStringDialog 显示如 Figure 1 所示的问号的呢?CStringDialog::Init 让你指定提示图标。默认是IDI_QUESTION。但 IDI_QUESTION 是一个内建的图标,不是来自应用程序资源文件的图标。如果你指定一个对话框模板中的资源 ID,Windows 期望它在资源文件中。那么我如何让 Windows 改用系统图标呢?
当然,话虽如此,CStringDialog 检查图标资源 ID,看看值是否大于 IDI_APPLICATION,也就是第一个系统图标的ID。如果该图标 ID 在系统 ID 范围之内,CStringDialog 通过调用::LoadIcon 来加载它,此时 hInstance 置为 NULL(用于系统图标)并在 数据成员 m_hIcon 中保存加载的HICON。然后 CStringDialog用0xFFFF + nResID 格式(nResID=0)来构造对话框模板。这导致 Windows 创建一个静态图标,但并非实际的图标,然后,CStringDialog 在 OnInitDialog 中才设置实际图标:
// in CStringDialog::OnInitDialog()
if (m_hIcon) {
CStatic* pStatic = (CStatic*)GetDlgItem(IDICON);
pStatic->SetIcon(m_hIcon);
}
这样一来,你可以将任何 IDI_XXX 形式的图标 IDs 传递给 CStringDialog::Init。你还能用自己的图标,只要其 ID 小于 IDI_APPLICATION = 32512。具体细节请参考源代码。
我最近要写一个正则表达式的DDV 确认程序,正巧你写了一个(参见 2005 四月刊)。想知道为什么你要包装 .NET 库,这样无端地添加了许多依赖性(包装库累赘),为什么不用Visual Studio .NET 里现成而简洁的正则表达式库,你只要包含一个头文件便可以在你的MFC 程序中使用它,atlrx.h?虽然它不是百分百标准的语法,但我宁愿用它而不愿添加对 .NET 框架的依赖。
更多精彩
赞助商链接