4

我已经按照这个问题制作了一个非模态/无模态对话框: 如何显示非模态 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

4 回答 4

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)

希望它可以帮助

于 2012-08-08T17:00:15.090 回答
3

如果你想删除无模式对话框,那么就这样做。

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

于 2012-08-09T09:56:02.807 回答
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,它应该正常重新创建对话框,然后返回正常操作。

于 2012-08-08T16:20:29.653 回答
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;
}
于 2012-08-09T07:35:25.283 回答