How can I programmatically detect if my MFC application currently is displaying a modal dialog or property sheet? Currently I'm using the following, but I feel that the code also triggers for modeless dialogs.
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;
}
Usage:
HasModalDialog(AfxGetMainWnd())
Anyone got a alternative way of detecting modal dialogs?
Have you tried CWnd::GetLastActivePopup
?
I haven't tested this to see if it'll work for modal dialogs only.
Edit 1: According to Raymond Chen, GetLastActivePopup
should return the current active modal dialog.
Edit 2: Perhaps another method to retrieve the current modal window would be to modify your code to check for a disabled parent/owner - modal dialogs should always disable their owner before displaying.
If you are only detecting windows within your application then you could derive your own CDialog and CPropertySheet and put a simple bool in there that keeps track of whether it is modal or not.
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;
}
There must be another way to do it but thats the only way I can think of off the top of my head.
I've tried many ways to solve that, why i needed that because i'm dealing with code that declare all the dialog as pointers to allocated in the heapmemory (TDialog* d = new TDialog) this was OWL code I converted it to MFC I want to delete those pointers automatically only if the dialog is modal it is not allocated in the heap, so i need to check for it my solution was easy to override the DoModal in my inherited class and set a flag isModal to true if it is not shown using DoModal the flag isModal will still null_ptr as it was initialized in the constructor
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;
}
}