运用无模式对话框
本文转载自本人在CSDN的博客,觉得很有用。http://blog.Windows对话框分为模式(Mode)和无模式(Modeless)两种。通常当屏幕最前面为模式对话框时,后面的对话框均不可用,这也是模式与无模式对话框的区别。
最直接的创造无模式对话框的方法是调用Create()函数,该函数需要传递一个对话框模版资源以及可选的父窗口指针。如果不传递父窗口指针则默认主窗口为其父窗口。当创建成功时将返回true。如果需要创建完毕后即显示该对话框,则需要WS_VISIBLE,否则需要调用ShowWindow(SW_SHOW)。
程序代码:
view plaincopy to clipboardprint?CModeLess *m_pmodeless = new CModeLess(this); m_pmodeless->Create(CModeLess::IDD); m_pmodeless->ShowWindow(SW_SHOW); CModeLess *m_pmodeless = new CModeLess(this); m_pmodeless->Create(CModeLess::IDD); m_pmodeless->ShowWindow(SW_SHOW);
当创建的无模式对话框显示后停留在父对话框(在Doc/View中则是主框架)之上,可以用于自窗口与父框架的交互操作。但是有些时候并不需要该无模式对话框总是停留在父框架之上,解决方法是在创造该对话框时将Create()中的父窗口指针传递给桌面窗口,使之成为桌面的一个子窗口。
view plaincopy to clipboardprint?m_pmodeless->Create(CModeLess::IDD,GetDesktopWindow()); m_pmodeless->Create(CModeLess::IDD,GetDesktopWindow());创建该对话框后系统为该对话框分配了存储空间,在该对话框销毁时必须销毁这些存储空间。当对话框关闭,该对话框接收到的最后一个消息是WM_NCDESTROY,OnNcDestroy()被调用并调用PostNcDestroy(),这里才算真正删除对话框。
程序代码:
view plaincopy to clipboardprint?void CModeLess::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; } void CModeLess::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; }
在将无模式对话框声明为父框架的一个对象时有一个指针指向该无模式对话框,现在将之删除之后该指针处于未知状态。一种解决方法是传递一个消息给父窗口将该指针设置为NULL。
程序代码:
view plaincopy to clipboardprint?void CModeLess::PostNcDestroy() { CDialog::PostNcDestroy(); GetParent()->PostMessage(WM_MODELESS_CLOSED,0,0); delete this; } void CModeLess::PostNcDestroy() { CDialog::PostNcDestroy(); GetParent()->PostMessage(WM_MODELESS_CLOSED,0,0); delete this; } view plaincopy to clipboardprint?LRESULT CMainFrame::OnMyMethod(WPARAM wParam, LPARAM lParam) { m_pmodeless = NULL; return 0; } LRESULT CMainFrame::OnMyMethod(WPARAM wParam, LPARAM lParam) { m_pmodeless = NULL; return 0; }在无模式对话框中要避免使用OnOK()和OnCancel()。若要使用必须改进如下。
程序代码:
view plaincopy to clipboardprint?void CModeLess::OnCancel() { DestroyWindow(); } void CModeLess::OnCancel() { DestroyWindow(); } view plaincopy to clipboardprint?void CModeLess::OnOK() { if(UpdateData(true)) { DestroyWindow(); } } void CModeLess::OnOK() { if(UpdateData(true)) { DestroyWindow(); } }在模式对话框中当DoModal()返回后依然可以访问该对话框的变量,因为该对话框对象并没有销毁只是窗口销毁了。在无模式对话框中依然实用。
程序代码:
view plaincopy to clipboardprint?void CModeLess::OnOK() { if(UpdateData(true)) { ((CMainFrame*)m_parent)->m_x=m_sss; DestroyWindow(); } } void CModeLess::OnOK() { if(UpdateData(true)) { ((CMainFrame*)m_parent)->m_x=m_sss; DestroyWindow(); } }
如果在一个父框架下只允许一个该无模式对话框实例存在,则需要进行如下程序。成员变量m_pmodeless表示无模式对话框的对象,如果该变量为NULL时则说明没有实例存在可以创建一个,当不为NULL时则调用SetForegroundWindow()将已存在的实例放在最窗口最前端。
程序代码:
view plaincopy to clipboardprint?if(m_pmodeless) { m_pmodeless->SetForegroundWindow(); } else { m_pmodeless = new CModeLess(this); m_pmodeless->Create(CModeLess::IDD); m_pmodeless->ShowWindow(SW_SHOW); } if(m_pmodeless) { m_pmodeless->SetForegroundWindow(); } else { m_pmodeless = new CModeLess(this); m_pmodeless->Create(CModeLess::IDD); m_pmodeless->ShowWindow(SW_SHOW); }
当该实例被销毁时需要告知父窗口m_pmodeless已经失效。
程序代码:
view plaincopy to clipboardprint?void CModeLess::PostNcDestroy() { CDialog::PostNcDestroy(); ((CMainFrame*)m_parent)->m_pmodeless = NULL; delete this; }