如何检测无模式CDialog是否已关闭?

时间:2012-08-08 16:20:30

标签: c++ visual-studio-2008 mfc dialog

我已按照此问题制作非模态/无模式对话框: 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;

如果对话框已被处理,是否需要继续监控?对话框关闭时是否有事件触发到父窗体?

4 个答案:

答案 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;
}