搜索
开启左侧

[资料] 模态对话框与非模态对话的几种销毁方法与区别

[复制链接]
IronMan 发表于 2016-12-21 13:25:03 | 显示全部楼层 |阅读模式

铂金VIP |主题 |帖子 |积分 7625

最近在做win32调对话框,挺郁闷,找了好多文章研究,才发现非常简单。

先说下模式对话框调用的原则。
模式对话框下,用CDialog::OnOK()或CDialog::OnCancel()以及CDialog::OnClose()关闭对话框。
一定要注意之前的CDialog::(当然,你可以重载你自己对话框的这个虚函数,但是,后面必须调用基类的CDialog::
具体我们再参照深入浅出的风格,来个解刨。


CDialog::Close()默认调用CDialog::OnCancel(),
CDialog::OnCancel()调用CDialog::EndDialog(IDCANCEL);
CDialog::EndDialog调用CDialog::DestroyWindows(),
CDialog::DestroyWindows调用CDialog::OnDestroy();

CDialog::OnOK()默认先CDialog::UpdateData()
再调用CDialog::EndDialog(IDOK).
CDialog::EndDialog调用CDialog::DestroyWindows(),
CDialog::DestroyWindows调用CDialog::OnDestroy()   



看来上面你可能就知道了如下的过程
CDialog::Close()==>CDialog::OnCancel()==>CDialog::EndDialog(IDCANCEL)
CDialog::OnOK()==>CDialog::EndDialog(IDOK)

CDialog::DestroyWindows()==>CDialog::OnDestroy()

CDialog::EndDialog(IDOK) ==   CDialog::UpdateData() + CDialog::DestroyWindows()==>CDialog::OnDestroy()


CDialog::EndDialog(IDOK)跟CDialog::EndDialog(IDCANCEL)的区别就是,少了一个CDialog::UpdateData(),也就是CDialog::EndDialog(IDOK),在关闭对话框后,会把对话框上控件关联的变量的值更新为用户最后输入的值。而CDialog::EndDialog(IDCANCEL)就不会更新这个值。
希望自己把模式对话框的关闭讲清楚了。

下面说说非模态对话框
调用原则是:  一定要用DestroyWindow()来结束非模态对话框...因为调用CDialog::Create() 时是在堆上 new的对象...需要DestroyWindow来delete 对象..不然会存在资源泄漏的风险...

在无模式对话框,重载你自己的OnOK(),就是CMyDialog::OnOK()调用CDialog::DestroyWindows()。
注意:不是默认的CDialog::OnOK()来关闭对话框。
重载CMyDialog::OnCancel()调用CDialog::DestroyWindows()。
注意:不是调用默认的CDialog::OnCancel(),来关闭对话框。

听起来很简单,但是下面提到一个很具体的编程问题。
一般,我们用非模态对话框都是全局的,也就是通过new来创建,是在heap上的,而不是在stack上的。
这样我们当然还要通过delete 来销毁对象,不然可是有内存泄漏的。那么我们什么时候delete这个对象呢?


在msdn上面我们可以看到微软提供的方法是,
我们要重载PostNcDestroy(),即我们要实现CMyDialog::PostNcDestroy(),内容如下
  1. CMyDialog::PostNcDestroy()  
  2. {   
  3.     CDialog::PostNcDestroy();  
  4.     delete this;   
  5. }  
复制代码
这样的话,我们的类就会Auto-Cleanup了。
  1. HWND hMain = CreateDialog(hInstance, (LPCTSTR)IDD_DIALOG1, hWnd,(DLGPROC)DlgProc);  
  2. ShowWindow(hMain, SW_SHOW);  
  3. SetTimer(hMain, 10, 5000, NULL);  
复制代码
仿造about处理消息改一下就好了。
  1. INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam,LPARAM lParam)  
  2. {  
  3.     switch(message)  
  4.     {  
  5.         case WM_COMMAND:  
  6.             if (wParam == IDOK)  
  7.             {  
  8.                 DestroyWindow(hDlg);  
  9.                 SendMessageW(hWnd,WM_ONOK, NULL, NULL);  
  10.                 break;  
  11.             }  
  12.             else if(wParam ==IDCANCEL)  
  13.             {  
  14.                 DestroyWindow(hDlg);  
  15.             }  
  16.        case WM_TIMER:  
  17.            if (wParam == 10)  
  18.            {  
  19.                SendMessageW(hWnd,WM_ONOK, NULL, NULL);  
  20.                DestroyWindow(hDlg);  
  21.                break;  
  22.            }  
  23.       return (INT_PTR)FALSE;  
  24. }  
复制代码



51Halcon.com 专注于机器视觉应用技术
vicky 发表于 2016-12-27 16:16:49 | 显示全部楼层

部门经理 |主题 |帖子 |积分 531

路过,学习一下!
51Halcon.com 专注于机器视觉应用技术
回复

使用道具 举报

Johnson@GZ 发表于 2016-12-28 23:16:25 | 显示全部楼层

部门助理 |主题 |帖子 |积分 436

其实也可以用C++11的shared_ptr智能指针自动释放
51Halcon.com 专注于机器视觉应用技术
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51Halcon机器视觉 | 粤ICP备15095995号-2|粤公网安备44030602000670号|

GMT+8, 2017-9-24 16:42 , Processed in 0.016109 second(s), 9 queries , Redis On.

快速回复 返回顶部 返回列表