我已按照此问题制作非模态/无模式对话框: How to display a non-modal CDialog?
我在VS2008中使用MFC / C ++。我使用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;
如果对话框已被处理,是否需要继续监控?对话框关闭时是否有事件触发到父窗体?
答案 0 :(得分:4)
如果要在使用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)
希望它可以提供帮助
答案 1 :(得分:3)
如果要删除无模式对话框,请执行此操作。
如果要在用户关闭无模式对话框时删除对话框的对象,可以查看WM_PARENTNOTIFY。如果子窗口被销毁且子窗口没有设置扩展窗口样式WS_EX_NOPARENTNOTIFY,则窗口会向父窗口发送带有wParam = WM_DESTROY的WM_PARENTNOTIFY。您应该在父窗口中为该消息实现一个处理程序,并检查它是否是正在销毁的无模式对话框。
答案 2 :(得分:1)
我已经起草了这个问题并准备发布它,但后来我有了一个想法并最终解决了我自己的问题。因此对于那些在检测到关闭无模式对话框时遇到问题的人来说,这就是我所做的:
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,因此应该正常重新创建对话框,然后返回正常操作。
答案 3 :(得分: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;
}