2009-08-19 3 views
4

Как я могу программным образом определить, показывает ли мое приложение MFC в настоящее время модальное диалоговое окно или лист свойств? В настоящее время я использую следующее, но я чувствую, что этот код также запускает для немодальных диалогов.Обнаружение модальных диалогов в MFC

bool HasModalDialog(const CWnd* pWnd) 
{ 
    const CWnd* pChildWnd = pWnd ? pWnd->GetNextWindow(GW_HWNDPREV) : NULL; 
    while (pChildWnd) 
    { 
     if (pWnd == pChildWnd->GetTopLevelParent() && 
     (pChildWnd->IsKindOf(RUNTIME_CLASS(CDialog)) || 
     pChildWnd->IsKindOf(RUNTIME_CLASS(CPropertySheet)))) 
     { 
     return true; 
     } 

     pChildWnd = pChildWnd->GetNextWindow(GW_HWNDPREV); 
    } 

    return false; 
} 

Использование:

HasModalDialog(AfxGetMainWnd()) 

Каждый получил альтернативный способ обнаружения модальные диалоговые окна?

+0

Я не вижу, как ваш код на самом деле определяет модальный диалог. Если CDialog или CPropertySheet были «Создать», тогда он будет немодальным, и ваш код будет STILL возвращать true. – Goz

+0

@Goz: Это проблема, из-за которой страдает код. – dalle

ответ

3

Вы попробовали CWnd::GetLastActivePopup?

Я не тестировал это, чтобы увидеть, будет ли оно работать только для модальных диалогов.


Edit 1: Согласно Raymond Chen, GetLastActivePopup должна возвращать текущее диалоговое окно активный модальный.

Edit 2: Возможно, еще один способ, чтобы получить текущее окно модального будет изменить код для проверки инвалида родителя/владельца - модальные диалоги должны всегда disable their owner перед выводом на экран.

0

Если вы только обнаруживаете окна в своем приложении, вы можете получить свой собственный CDialog и CPropertySheet и разместить там простой bool, который будет отслеживать, является ли он модальным или нет.

bool HasModalDialog(const CWnd* pWnd) 
{ 
    const CWnd* pChildWnd = pWnd ? pWnd->GetNextWindow(GW_HWNDPREV) : NULL; 
    while (pChildWnd) 
    { 
     if (pWnd == pChildWnd->GetTopLevelParent()) 
     { 
     if (pChildWnd->IsKindOf(RUNTIME_CLASS(CMyDialog)) 
     { 
      return ((CMyDialog*)pChildWnd)->IsModal(); 
     } 

     if (pChildWnd->IsKindOf(RUNTIME_CLASS(CMyPropertySheet)) 
     { 
      return ((CMyPropertySheet*)pChildWnd)->IsModal(); 
     } 
     } 
     pChildWnd = pChildWnd->GetNextWindow(GW_HWNDPREV); 
    } 

    return false; 
} 

Там должен быть другой способ сделать это, но тот единственный способ, которым я могу думать с верхней части моей головы.

+0

К сожалению, для этого требуется, чтобы все диалоги были получены из этих новых классов, и это не будет работать для классов диалога, уже находящихся в MFC. – dalle

+0

действительно нет. Вы должны были бы сделать свои собственные обертки класса для них тоже ... было бы чертовски хреново ... – Goz

0

Я пробовал много способов решить это, почему мне это нужно, потому что я имею дело с кодом, объявляющим все диалоговое окно как указатели, выделенные в heapmemory (TDialog * d = new TDialog), это был код OWL I преобразовал его в MFC. Я хочу, чтобы эти указатели автоматически удалялись, только если диалог является модальным, он не выделяется в куче, поэтому мне нужно проверить его. Мое решение было легко переопределить DoModal в моем унаследованном классе и установить флаг isModal для истинно, если оно не отображается, используя DoModal флаг isModal будет еще null_ptr как он был инициализирован в конструкторе

class : public CDialog 
{ 
    private: 
     bool isModal 
    public: 
     CMyDlg(int id, CWnd* parent = NULL) : CDialog(id, parent), isModal(false) 
     { 

     } 

     virtual INT_PTR DoModal() 
     { 
      isModal = true; 
      return CDialog::DoModal();//return __super::DoModal(); 
     } 

     bool IsModal() 
     { 
      return isModal; 
     } 

     virtual void OnCancel() 
     { 
      if(isModal) 
      { 
       CDialog::OnCancel(); 
      } 
      else 
      { 
       DestroyWindow(); 
      } 
     } 

     virtual void OnOk() 
     { 
      if(isModal) 
      { 
       CDialog::OnCancel(); 
      } 
      else 
      { 
       DestroyWindow(); 
      } 
     } 
     virtual void PostNcDestroy() 
     { 
      delete this; 
     } 
} 
Смежные вопросы