模态对话框与非模态对话的几种销毁方法与区别
2015-06-11 14:00
267 查看
最近在做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()
[b]CDialog::EndDialog(IDOK)
== [/b][b]CDialog::[/b]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(),内容如下
[cpp]
view plaincopyprint?
CMyDialog::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; }
这样的话,我们的类就会Auto-Cleanup了。
[cpp]
view plaincopyprint?
HWND hMain = CreateDialog(hInstance, (LPCTSTR)IDD_DIALOG1, hWnd,(DLGPROC)DlgProc); ShowWindow(hMain, SW_SHOW); SetTimer(hMain, 10, 5000, NULL);
仿造about处理消息改一下就好了。
[cpp]
view plaincopyprint?
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_COMMAND:
if (wParam == IDOK)
{
DestroyWindow(hDlg);
SendMessageW(hWnd,WM_ONOK, NULL, NULL);
break;
}
else if(wParam ==IDCANCEL)
{
DestroyWindow(hDlg);
}
case WM_TIMER:
if (wParam == 10)
{
SendMessageW(hWnd,WM_ONOK, NULL, NULL);
DestroyWindow(hDlg);
break;
}
return (INT_PTR)FALSE;
}
先说下模式对话框调用的原则。
在模式对话框下,用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()
[b]CDialog::EndDialog(IDOK)
== [/b][b]CDialog::[/b]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(),内容如下
[cpp]
view plaincopyprint?
CMyDialog::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; }
CMyDialog::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; }
这样的话,我们的类就会Auto-Cleanup了。
[cpp]
view plaincopyprint?
HWND hMain = CreateDialog(hInstance, (LPCTSTR)IDD_DIALOG1, hWnd,(DLGPROC)DlgProc); ShowWindow(hMain, SW_SHOW); SetTimer(hMain, 10, 5000, NULL);
HWND hMain = CreateDialog(hInstance, (LPCTSTR)IDD_DIALOG1, hWnd,(DLGPROC)DlgProc); ShowWindow(hMain, SW_SHOW); SetTimer(hMain, 10, 5000, NULL);
仿造about处理消息改一下就好了。
[cpp]
view plaincopyprint?
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_COMMAND:
if (wParam == IDOK)
{
DestroyWindow(hDlg);
SendMessageW(hWnd,WM_ONOK, NULL, NULL);
break;
}
else if(wParam ==IDCANCEL)
{
DestroyWindow(hDlg);
}
case WM_TIMER:
if (wParam == 10)
{
SendMessageW(hWnd,WM_ONOK, NULL, NULL);
DestroyWindow(hDlg);
break;
}
return (INT_PTR)FALSE;
}
相关文章推荐
- 【Android】Tab页的实现,利用tabhost
- 【Android】Tab页的实现,利用tabhost
- hdoj 1465 不容易系列之一
- java 多线程(wait/notify/notifyall)
- mysql复制原理
- 用于 ‘Suse‘ Linux 包管理的 Zypper 命令大全
- 用于 ‘Suse‘ Linux 包管理的 Zypper 命令大全
- Ajax的jsonp方式跨域获取数据
- Ubuntu安装flash player
- Windows Storage Server 2012建立iSCSI虚拟磁盘存储
- I2C上拉电阻取值问题
- 技术七Gitservergitolite要构建和操作方便
- 【性能诊断】一、开篇
- tomcat 配置虚拟路径
- java 多线程(synchronized)
- tcpdump
- ImportError: libxml2.so.2: cannot open shared object file: No such file or directory
- Dynamics CRM2015 2015版本可用的OData Query Designer工具
- HDU--2087
- Dynamics CRM2015 2015版本可用的OData Query Designer工具