MFC窗体关闭那点事

来源:互联网 发布:手机导航需要网络吗 编辑:程序博客网 时间:2024/05/22 12:13

转载请注明出处

作者:小马

网上没找到说得比较清楚的,自己发表一些看法, 讲几个相关的知识点. 以备日后脑子不好使了, 可以找来温习一下.

 

当我们用创建一个新的对话框时, 上面会有两个按钮, 他们的ID是IDOK和IDCANCEL,这两个ID是MFC的保留ID,任何按钮,不管它叫什么名字,只有他们的ID是这两个, 如果你不重载他们(在资源视图双击后,添加自己的代码), 点一下的效果都是关闭窗体.

 

虽然效果是一样的, 但是底层调用确是有差异的, IDOK实际动作是调用了CDialog::OnOK(), 而IDCANCEL是调用CDialog::OnCancel().可以看一下这两个基类函数的源码(设个断点,F11跟进去可以看到源码)

void CDialog::OnOK(){ if (!UpdateData(TRUE)) {  TRACE0("UpdateData failed during dialog termination./n");  // the UpdateData routine will set focus to correct item  return; } EndDialog(IDOK);}void CDialog::OnCancel(){ EndDialog(IDCANCEL);}


他们都调用了EndDialog.

来说说这个EndDialog, msdn上如是说:

Call this member function to terminate a modal dialog box.这个就是最终用来结束模态对话框的底层API函数, 它的参数用来传给"the caller of DoModal", 

这就是为什么我们可以用类似
if(dlg.DoModal()==IDOK)
语句类判断用户点击的是"ok"还是"cancel".

 

两个函数唯一的区别就是OnOK多调了一个UpdateData的函数, 这个函数应该不会太陌生,
它负责控件和变量之间的数据交换和更新. 它的参数为TRUE表示数据由控件赋值给变量.

 

想到两个问题:

第一个问题, 在什么样的应用场合都体现出OnOK和OnCancel的差别呢?


你可以先在这里想一会儿......,不过我要继续写.

 

试想下面一种情况, dialog1窗体上有一个button,点这个button调起一个模态的对话框dialog2, dialog2上有一个edit box控件, 关联一个CString型的变量叫m_str.
在dialog2从DoModal函数返回时, 读m_str的值, 你会发现,如果你是点dialog2上的OK返回, m_str的值就是你在edit box里输入的字符串, 如果你点Cancel返回, m_str是空值.

 

第二个问题, 是你应该认识到的, 如果你在结束对话框之前, 已经销毁了一些具体关联关系的控件(比如调用了DestroyWindow), 然后你用OnOK来关闭窗体,程序肯定会崩溃.

 

MFC的窗体有这样的两个消息, 分别是WM_CLOSE和WM_DESTROY.

在win32时代, 一个标准的windows窗体(用CreateWindow建立), 当你点击右上角的X时,
系统送出WM_CLOSE消息, 程序不必处理,直接交由DefWindowProc来处理, 而它处理的操作就是调用
DestroyWindow, 而DestroyWindow会送出WM_DESTROY. 你的程序响应WM_DESTROY标准处理流程是释放资源,然后调用PostQuitMessage函数.


PostQuitMessage会引出WM_QUIT消息(这个消息完全不用理会,系统自己处理), 系统检测这个消息,退出程序.

 

MFC对上述操作做了封装, 很多细节可以不必理会. 比如在MFC应用中, 已经很难看到PostQuitMessage的身影了. 这个函数在MFC中要慎用,因为它是关闭窗体的最后一步了, 如果你在不恰当的地方调用了它,可能MFC本身一些默认的处理得不到执行, 从而程序出现错误.

 

我们可以响应上述两个消息(WM_CLOSE和WM_DESTROY)然后做一些特殊化的处理.
比如,WM_CLOSE,我们可以在适当的地方通过SendMessage来向窗体发出这个消息, 完成一些操作.
而WM_DESTROY消息则最好不要由程序自己发送,这个消息应该无论任何时候,都应该由系统来发送.

 

对于MFC的对话框应用, 如果我们拦截WM_CLOSE和WM_DESTROY消息, 就会发现, 当你点击窗体右上角的"X"时,
程序会先响应WM_CLOSE,再响应WM_DESTROY.但是正像前面讲到的, MFC中, 对话框程序基本采用OnOK或OnCancel的形式来关闭,拦截WM_CLOSE或WM_DESTROY的意义不大.

 

仅一家之言, 欢迎拍砖!

原创粉丝点击