非模式对话框
非模式对话框(翻译自vc技术内幕第五版 第二部分 第七章,如有错误之处敬请指正)
模式和非模式对话框使用同一个基类——CDialog类,他们都使用由对话框编辑器创建的对话框资源。如果你在一个视图中用到一个非模式对话框,那就需要一些专门的编程技术。
创建非模式对话框
对于一个模式对话框来说,使用CDialog类的构造函数来创建一个对话框对象,该构造函数的一个参数是资源模板的ID号,完成构造以后,调用对话框对象的DoModal成员函数即可显示模式对话框。当DoModal返回后,对话框窗体将不再存在。因此,可以在栈空间创建一个模式对话框,推论可知,C++对话框对象离开有效区域后,对话框窗体已经释放掉了。
非模式对话框更加复杂,从调用Dialog类的默认构造函数开始构建一个对话框对象,但是,要创建一个对话框窗体,需要调用CDialog::Create成员函数而不是DoModal函数。Create函数有一个参数是资源ID,然后,对话框窗体还在屏幕上就直接返回了。这就需要明确的考虑何时创建对话框对象、何时创建对话框窗体、何时释放对话框对象和何时处理用户输入的数据。
以下是对创建模式对话框和非模式对话框不同点的总结:
模式对话框 非模式对话框
用到的构造函数 构造函数使用资源ID参数 默认构造函数(无参数)
创建窗体用到的函数 DoModal 以资源ID为参数的Create函数
用户自定义消息
假如你想要在用户点击OK按钮时释放非模式对话框,这里存在一个问题,视图(View)如何知道用户点击了OK按钮呢?对话框可以直接调用视图类的成员函数,但这样就将对话框“嫁给”了特定的视图类。一个更好的解决方法是对话框发送给视图(View)一个用户自定义的消息作为OK按钮消息处理函数的调用结果。当视图得到这个消息,就释放对话框窗体(而不是对话框对象)。给创建新对话框奠定了基础。
发送Windows系统消息具有两个可选方法,CWnd::SendMessage函数或者PostMessage函数,前一个引发消息处理函数的立即调用,后一个传递一个消息给Windows消息队列。由于选用PostMessage具有少许的延迟,完全有理由认为:当视图(View)获得消息后,处理函数(对话框窗体的?)已经返回了。实验记录:使用PostMessage方法,单步调试,断点到PostMessage方法,单步运行,断点到PostMessage函数所在行的下一行;使用SendMessage方法,单步调试,断点到PostMessage方法,单步运行,断点到对应的消息映射函数。
对话框的所有权
假设你接受了对话框的默认pop-up风格,这意味着对话框将不限制在视图(View)的客户区域。就Windows所关心的,对话框的所有者是应用程序的主框架窗口(第13章介绍),而不是视图。这就需要知道对话框的视图,以便给视图发送消息。因此,对话框类必须通过构造函数所设定的数据成员来跟踪他所拥有的视图。CDialog类构造函数的pParent参数在此没有任何意义,所以不要烦扰他。