2012-08-08 4 views
1

J'ai suivi cette question pour faire une boîte de dialogue/modeless non modale: How to display a non-modal CDialog?Comment détecter si un CDialog non modal a été fermé?

J'utilise MFC/C++ dans VS2008. Je suis plus couramment avec C# et .net qu'avec MFC et C++.

J'ai un élément de menu dans mon formulaire qui lance la boîte de dialogue. Il ne peut y avoir qu'une seule instance de la boîte de dialogue ouverte. La boîte de dialogue s'affiche correctement. Je peux le fermer en cliquant sur le X dans le coin et il se ferme lorsque je ferme le formulaire principal. Le problème que j'ai est le dialogue ne peut pas être ouvert à nouveau après que je clique sur le X pour fermer la boîte de dialogue. Je sais que c'est parce que le pointeur n'est jamais en arrière à NULL.

je ce dans le fichier d'en-tête de ma forme:

CChildDialog *m_pDialog; 

Je cette partie dans le constructeur de ma forme:

m_pDialog = NULL; 

En cliquant sur un élément de menu que j'ai ce code dans de l'élément de menu méthode (je l'ai modifié à partir de l'autre réponse SO parce que je veux seulement une instance de la boîte de dialogue ouverte):

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); 
} 

Maintenant, je sais que je dois exécuter cette partie et régler le pointeur NULL, mais je ne sais pas où mettre ceci:

// Delete the dialog once done 
delete m_pDialog; 
m_pDialog = NULL; 

Dois-je continuer à surveiller si le dialogue a été disposé? Y a-t-il un événement déclenché au formulaire parent lorsque le dialogue est fermé?

+2

Ajoutez simplement un gestionnaire de message pour WM_DESTROY qui réinitialise le pointeur. –

Répondre

3

Si vous voulez recycler le contenu de la fenêtre après la fermeture avec X, vous devez gérer le message WM_CLOSE dans votre boîte de dialogue:

void CChildDialog::OnClose() 
{ 
    ShowWindow(SW_HIDE); 
} 

Puis dans le code qui ouvre la fenêtre:

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) 

espoir peut aider

0

J'ai fait rédiger la question et j'étais prêt à la poster, mais j'ai eu une idée et j'ai fini par résoudre mon propre problème. Donc, pour quelqu'un d'autre qui a un problème avec la détection de la fermeture d'une boîte de dialogue modales, voici ce que je faisais:

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(); 
    } 
} 

Je viens fini vérifier si la boîte de dialogue modales est visible après avoir cliqué sur l'élément de menu du formulaire. Si c'est visible, ne faites rien. Si ce n'est pas le cas, détruisez la boîte de dialogue non visible existante, définissez le pointeur sur NULL et appelez de nouveau la méthode de manière récursive. Puisque le pointeur est maintenant NULL, il devrait recréer la boîte de dialogue normalement, puis revenir en mode normal.

+0

Que se passe-t-il si vous fermez la boîte de dialogue mais que vous n'avez plus jamais cliqué sur le menu? fuite de mémoire potentielle – Jeeva

0

vous devez supprimer la mémoire PostNcDestroy comme celui-ci

void CChildDialog ::PostNcDestroy() 
{ 
    CDialog::PostNcDestroy(); 
    GetParent()->PostMessage(WM_WIN_CLOSED,0,0); 
    delete this; 
} 

et d'envoyer un message défini par l'utilisateur à la fenêtre parente que votre fenêtre est fermée. Dans la fenêtre parent ajouter un gestionnaire de messages pour WM_WIN_CLOSED comme

LRESULT CMainDialog::OnMyMethod(WPARAM wParam, LPARAM lParam) 
{ 
    m_pDialog = NULL; 
    return 0; 
} 
1

Si vous souhaitez supprimer la boîte de dialogue modales, puis faites tellement.

Si vous souhaitez supprimer l'objet de la boîte de dialogue lorsque l'utilisateur a fermé la boîte de dialogue non modale, vous pouvez consulter WM_PARENTNOTIFY. Si une fenêtre enfant est détruite et que la fenêtre enfant n'a pas le jeu de styles de fenêtre étendu WS_EX_NOPARENTNOTIFY, alors Windows envoie un WM_PARENTNOTIFY avec wParam = WM_DESTROY à la fenêtre parente. Vous devez implémenter un gestionnaire pour ce message dans la fenêtre parente et vérifier si c'est la boîte de dialogue non modale qui est en train d'être détruite.

Questions connexes