visual-c++mfcdialogcdialog

Problem with a non-modal, self-closing dialog in combination with other dialogs


It is about a MFC-MDI application. I have added a popup window, which should be closed after some duration. Therefore, I create a non-modal dialog

CPopupDlg* pDlg = new CPopupDlg(this);
if (pDlg)
{
    pDlg->Create(IDD, this);
    pDlg->ShowWindow(SW_SHOW);
}

It will be closed by a Timer and destroyed in OnNcDestroy()

void CPopupDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == m_CounterEventID)
    {
        KillTimer(nIDEvent);
        EndDialog(IDCANCEL);
        DestroyWindow();
    }
}

void CPopupDlg::OnNcDestroy()
{
    __super::OnNcDestroy();
    delete this;
}

My problem are many other (modal) dialogs and message boxes, which may appear, while the CPopupDlg is open. These modal dialogs often does not specify a parent window in my project (CDialogconstructor with pParentWnd=NULL). Hence, the method CDialog::DoModal() use ::GetLastActivePopup() to determine its parent window. The CPopupDlg dialog is chosen as the parent window. As a consequence, DoModal() crashes, when the CPopupDlg window is closed by the timer.

How can I tackle this problem?

  1. Is there a way to exclude the CPopupDlg dialog from the results of ::GetLastAcitvePopup()?

  2. Sometimes I have seen, that non-modal dialogs uses RunModalLoop(). Would this be the solution?

    popupDlg.Create(IDD, this);
    popupDlg.RunModalLoop(MLF_SHOWONIDLE);
    popupDlg.DestroyWindow();
  1. What would happen, if the popup dialog would never be closed and destroyed, but only hidden. Would other modal dialog windows, which are undesired childs of the CPopupDlg wnd, also disappear, if popupDlg.ShowWindow(SW_HIDE) is called?

Solution

  • My solution is to create the popup window as a separate desktop child window. It is not a child window of the application and will not be chosen by ::GetLastActivePopup().

    CPopupDlg* pDlg = new CPopupDlg(this);
    if (pDlg)
    {
        pDlg->Create(IDD, GetDesktopWindow());
        pDlg->ShowWindow(SW_SHOW);
    }