2012-08-08 76 views
1

我都遵循这个问题做一个非模态/非模态对话框: How to display a non-modal CDialog?如何检测无模式CDialog是否已关闭?

我使用MFC/C++在VS2008。我比C#和.net的流畅度高于MFC和C++。

我有一个菜单项在我的表单启动对话框。只能有一个打开的对话框实例。该对话框显示正常。我可以通过点击拐角处的X来关闭它,当我关闭主窗体时它会关闭。我遇到的问题是在单击X关闭对话框后无法再次打开对话框。我知道这是因为指针永远不会回到NULL。

我有这个在我的窗体的头文件:

CChildDialog *m_pDialog; 

我有这部分我的窗体构造函数:

m_pDialog = NULL; 

当我在菜单项的验证码菜单项点击方法(我从另一个SO修改它,因为我只想要打开一个对话框的实例):

if(m_pDialog == NULL) 
{ 
    // Invoking the Dialog 
    m_pDialog = new CChildDialog(); 
    BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this); 

    if (!ret) //Create failed. 
    { 
     AfxMessageBox(_T("Error creating Dialog")); 
    }  

    m_pDialog->ShowWindow(SW_SHOW); 
} 

现在我知道我需要执行此部分,并设置指针为NULL,但我不知道在哪里把这个:

// Delete the dialog once done 
delete m_pDialog; 
m_pDialog = NULL; 

我是否需要,如果对话框已被释放,以保持监控?关闭对话框时是否触发了父窗体?

+2

只需为WM_DESTROY添加一个消息处理程序来重置指针。 – 2012-08-08 17:40:18

回答

3

如果你想与X关闭它后回收窗口的内容,你必须处理您的对话框中的WM_CLOSE消息:在打开的窗口中的代码

void CChildDialog::OnClose() 
{ 
    ShowWindow(SW_HIDE); 
} 

然后:

if(m_pDialog == NULL) 
{ 
    // Invoking the Dialog 
    m_pDialog = new CChildDialog(); 
    BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this); 

    if (!ret) //Create failed. 
    { 
     AfxMessageBox(_T("Error creating Dialog")); 
    }  
} 

m_pDialog->ShowWindow(SW_SHOW); //moved outside the if(m_pDialog == NULL) 

希望它可以帮助

0

我已经准备好了这个问题,并准备发布它,但后来我有了一个想法,最终解决了我自己的问题。因此,对于谁比谁有检测无模式对话框的关闭的问题,这是我做的:

void Form1::MenuItemMethod() 
{ 
    if(m_pDialog == NULL) 
    { 
     // Invoking the Dialog 
     m_pDialog = new CChildDialog(); 
     BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this); 

     if (!ret) //Create failed. 
     { 
      AfxMessageBox(_T("Error creating Dialog")); 
     }  

     m_pDialog->ShowWindow(SW_SHOW); 
    } 
    else 
    { 
     // cannot check if visible at the beginning of method because 
     // pointer could be NULL and will throw an exception 

     if(m_pDialog->IsWindowVisible()) 
     { 
      return; 
     } 

     m_pDialog->DestroyWindow(); 
     m_pDialog = NULL; 
     MenuItemMethod(); 
    } 
} 

我刚刚结束了检查,如果无模式对话框再次点击窗体的菜单项后可见。如果可见,则不要做任何事情。如果不是,则销毁现有的不可见对话框,将指针设置为NULL,并再次递归调用该方法。由于指针现在为NULL,它应该正常重新创建对话框,然后返回到正常操作。

+0

如果关闭对话框但会再次单击菜单,会发生什么情况?潜在的内存泄漏 – Jeeva 2012-08-09 07:39:09

0

你必须删除存储在PostNcDestroy这样

void CChildDialog ::PostNcDestroy() 
{ 
    CDialog::PostNcDestroy(); 
    GetParent()->PostMessage(WM_WIN_CLOSED,0,0); 
    delete this; 
} 

并将用户定义的消息发送到窗口关闭的父窗口。在父窗口中添加一个消息处理程序WM_WIN_CLOSED

LRESULT CMainDialog::OnMyMethod(WPARAM wParam, LPARAM lParam) 
{ 
    m_pDialog = NULL; 
    return 0; 
} 
1

如果要删除无模式对话框,然后就这样做。

如果您想在用户关闭无模式对话框时删除对话框的对象,则可以查看WM_PARENTNOTIFY。如果一个子窗口被销毁并且子窗口没有设置扩展窗口样式WS_EX_NOPARENTNOTIFY,那么Windows会将一个WM_PARENTNOTIFY与wParam = WM_DESTROY发送到父窗口。您应该在父窗口中为该消息实现一个处理程序,并检查它是否是正在销毁的无模式对话框。