当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 对话框模板,RegexTest

VC++
如何在运行时确定对象类型(RTTI)
FMD开发文集 -- CArchive原理
FMD开发文集 -- MFC调试模式下new操作符的特殊处理
FMD开发文集 -- MFC CObject浅析
生死疆界(下)--- 在new与delete之间
生死疆界(上)--- 在new与delete之间
Pointers 与 References(四)
Pointers 与 References(三)
Pointers 与 References(二)
Pointers 与 References(一)
介绍一个专门处理C++异常的类和例子
关于构造单实例类的一个问题
模板友元化
C++中类的数据成员的安全隐患
关于对象生命历程的会话
接触VC之二:MFC类基础,C++程序编写规范介绍
内联汇编基础知识
命名空间的概念
捕获数学函数异常
MMX指令集在C++中的使用

VC++ 中的 对话框模板,RegexTest


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 126 ::
收藏到网摘: n/a

C++ At Work 专栏...
对话框模板,RegexTest

原著:Paul DiLascia
翻译:NorthTibet

下载源代码:CAtWork0508.exe (279KB)
原文出处:Dialog Templates, RegexTest

  • 对话框模板
  • RegexTest


我想用 MFC 和 C++ 创建一个基于对话框的程序(主窗口本身是个对话框)。我不想使用资源(.rc)文件,而是想在内存中动态创建对话框。我在 MSDN 中找到一些线索,但没有发现代码例子。我了解到 DLGTEMPLATE 和 DLGITEMTEMPLATE 结构以及 InitModalIndirect 函数或许可以用来创建模式对话框,但我不知道从何入手。请问如何不依赖资源文件动态创建对话框?

Thomas Zeitlberger
从理论上讲,动态创建对话框很简单,但实际上那样做很危险。就是内存中创建正确的结构并调用一系列 Indirect 对话框创建函数之一:用 CDialog::CreateIndirect 创建非模式对话框,或者用 CDialog::InitModalIndirect 创建模式对话框(然后调用 DoModal 运行)。它们分别对应着 Win32 API 函数 ::CreateDialogIndirect 和 ::DialogBoxIndirect。不管用什么方法,你都得在内存中传递一个指向对话框模板的指针。
  从概念上讲,创建对话框模板很简单,就是在内存中建立并初始化相关结构。其具体细节是有讲究的,因为这些结构有点奇奇怪怪,很诡诈,你不得有一点差错,只要有一个字节的偏差,那么你的程序便会莫名其妙地垮掉。控件的位置和大小计算也会出现混乱,原因是对话框不使用像素,而是用对话框单位(units),它依赖对话框的字体。
  要完整地讨论包含所有类型控件的对话框模板不是本专栏所能胜任的。但我可以提供一个简单的例子,它至少包含一个控件。我写了一个类:CStringDialog,它显示一个对话框,请求用户输入一个字符串,如图 Figure 1 所示。


Figure 1 String Dialog

为了使用这个类,你只需实例化然后调用 Init 和 DoModal 即可:
CStringDialog dlg;dlg.Init(_T("Hi"), _T("Please enter your name:"));if (dlg.DoModal()==IDOK) { CString name = dlg.m_str; // do something with it...}

  CStringDialog 的样子和行为类似于所有基于对话框资源的 CDialog 派生类,所不同的是该对话框用其自身模板在内存中动态生成。
  那么对话框模板到底是个什么东西呢?对话框模板其实就是一个描述对话框的内存结构。这个模板之所以复杂并容易出错,是因为它并非像 CREATESTRUCT 和 WNDCLASS 一样是个定长结构。它是一个变长结构,其中包含有定长结构元素 DLGTEMPLATE 以及 DLGITEMTEMPLATE 结构数组,其每个数组元素对应着一个对话框控件项。DLGTEMPLATE 和 DLGITEMTEMPLATE 两者都包含一些跟在 C 结构后面非常很特别的变长域。这些结构如 Figure 2 所示,Figure 3 是整个结构的布局。

 
Figure 3 对话框模板

  对话框模板有点像汇编语言编程手册中的内容,现在就让我们穿上蹩脚的工作制服,立即从 DLGTEMPLATE 开始吧。
  假设你分配了一块足够大的内存来存放整个对话框模板,首先要做的事情就填写 DLGTEMPLATE 结构域。这一部分不难:

WORD* pTempl = new WORD[1024];DLGTEMPLATE& dt = *((DLGTEMPLATE*)pTempl);dt.style = WS_POPUPWINDOW|DS_MODALFRAME|WS_DLGFRAME;dt.cdit = 3; // # dlg itemsdt.x = 100; // in dlg units// etc.

  DLGTEMPLATE 结构域是自扩展的,对此我不再做进一步说明。紧跟着该结构后面的域是变长域:菜单,对话框类和标题。每一项都不能超过一个 WORD。它可以是一个空结尾的 Unicode 字符串以标示某个 MENU 资源的名字,对话框类名或标题。此外,菜单和类名可以用特殊值 0xFFFF 后跟一个 16位 的 ID——即可以是菜单资源的 ID,也可以是预定义系统窗口类的序数。在大多数情况下,类名都应该使用 0x0000(空串),它告诉 Windows 操作系统使用默认的对话框类(#32770)。多数对话框都没有菜单,所以菜单也是 0x0000(空串)。在代码中是这样写的:

*pTempl++ = 0; // 菜单 (无)*pTempl++ = 0; // 对话框类 (使用标准的对话框类)

接下来是标题,一个空结尾的 Unicode 字符串:

USES_CONVERSION;LPCWS