代码之家  ›  专栏  ›  技术社区  ›  Alex

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

  •  4
  • Alex  · 技术社区  · 14 年前

    我根据这个问题制作了一个非模态/非模态对话框: 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 回复  |  直到 9 年前
        1
  •  4
  •   Albertino80    14 年前

    如果您想在用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)
    

    希望能有所帮助

        2
  •  3
  •   Werner Henze    6 年前

    如果您想删除无模式对话框,那么只需删除即可。

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

        3
  •  1
  •   Alex    14 年前

    我起草了这个问题并准备发布,但后来我有了一个想法,最终解决了我自己的问题。因此,对于其他在检测非模态对话框关闭时有问题的人,我是这样做的:

    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,它应该正常地重新创建对话框,然后返回正常操作。

        4
  •  0
  •   Jeeva    14 年前

    你必须删除中的内存 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;
    }