Partager via


TN017 : Objets de destruction window

Cette remarque décrit l'utilisation de la méthode de CWnd::PostNcDestroy .Utilisez cette méthode si vous souhaitez que l'allocation personnalisée d' CWndobjets dérivés de.Cette remarque explique également pourquoi vous devez utiliser CWnd::DestroyWindow pour détruire l'objet de fenêtres C++ au lieu de l'opérateur d' delete .

Si vous suivez les instructions de cette rubrique, vous aurez peu de problèmes de nettoyage.Ces problèmes peuvent résulter des problèmes tels qu'oublier de supprimer/mémoire libre C++, oublier de libérer les ressources système comme HWNDs, ou supprimer des objets trop grand nombre de fois.

Le problème

Chaque objet windows (objet d'une classe dérivée d' CWnd) représente un objet C++ et HWND.Les objets C++ sont alloués dans le tas d'application et HWNDs sont alloués dans les ressources système par le gestionnaire de fenêtrage.Comme il existe plusieurs façons de détruire un objet window, nous devons fournir un ensemble de règles qui empêchent la ressource système ou les fuites de mémoire.Ces règles doivent également empêcher les objets et les handles de fenêtres d'être détruite plusieurs fois.

Fenêtres de destruction

Voici les deux méthodes autorisées de détruire un objet de windows :

  • Appeler CWnd::DestroyWindow ou l'API Windows DestroyWindow.

  • Explicitement supprimant avec l'opérateur d' delete .

Le premier cas est de loin plus courantes.Ce cas s'applique même si votre code n'appelle pas DestroyWindow directement.Lorsque l'utilisateur ferme directement une fenêtre frame, cette action génère le message d' WM_CLOSE , et les réponses par défaut à ce message est d'appeler **DestroyWindow.**lorsqu'une fenêtre parente est détruite, windows appelle DestroyWindow pour tous ses enfants.

Le deuxième cas, l'utilisation de l'opérateur d' delete sur les objets de windows, doit être rare.Voici quelques cas où l'utilisation de delete est le choix correct.

Nettoyage automatique avec CWnd::PostNcDestroy

Lorsque le système détruit une fenêtre de windows, le dernier message windows envoyé à la fenêtre est WM_NCDESTROY.Le gestionnaire par défaut d' CWnd pour ce message est CWnd::OnNcDestroy.OnNcDestroy détachera HWND de l'objet C++ et appelle la fonction virtuelle PostNcDestroy.Certaines classes substituent cette fonction pour supprimer l'objet C++.

L'implémentation par défaut d' CWnd::PostNcDestroy ne fait rien, qui est appropriée pour les objets window qui sont alloués sur le frame de pile ou incorporés dans d'autres objets.Ce n'est pas utile pour les objets window conçus pour être alloués sur le tas sans aucun autre objet.En d'autres termes, il n'est pas approprié pour les objets window qui ne sont pas incorporés dans d'autres objets C++.

Ces classes qui sont conçues seul pour être allouées sur la substitution de tas la méthode d' PostNcDestroy pour effectuer delete this.Cette instruction permet de libérer toute mémoire associée à l'objet C++.Bien que le destructeur d' CWnd par défaut appelle DestroyWindow si m_hWnd est non null, cela ne mène pas à la récurrence infinie car le handle se détaché et NULL pendant la phase de nettoyage.

[!REMARQUE]

Le système appelle généralement CWnd::PostNcDestroy après qu'elle a le message d' WM_NCDESTROY windows et HWND et l'objet fenêtre C++ ne sont plus connectés.Le système appelle également CWnd::PostNcDestroy dans l'implémentation de la plupart des appels de CWnd::Create si l'erreur se produit.Les règles automatiques de nettoyage sont décrites plus loin dans cette rubrique.

Classes automatiques de nettoyage

Les classes suivantes ne sont pas conçues pour l'automobile-CleanUp.Ils sont généralement incorporés dans d'autres objets C++ ou sur la pile :

  • Tous les contrôles Windows standard (CStatic, CEdit, CListBox, etc.).

  • Toutes fenêtres enfants dérivées directement d' CWnd (par exemple, des contrôles personnalisés).

  • Fenêtres fractionnées (CSplitterWnd).

  • Barres de contrôles par défaut (les classes dérivées d' CControlBar, consultez note technique 31 pour activer l'automobile-suppression pour les objets de barre de contrôles).

  • Boîtes de dialogue (CDialog) conçus pour les boîtes de dialogue modales sur le frame de pile.

  • Tous les boîtes de dialogue standard à l'exception CFindReplaceDialog.

  • Les boîtes de dialogues par défaut créés par l'assistant classe.

Les classes suivantes sont conçues pour l'automobile-CleanUp.Ils sont généralement seuls alloués sur le tas :

  • Fenêtres frames principales (dérivées directement ou indirectement d' CFrameWnd).

  • Fenêtres d'affichage (dérivées directement ou indirectement d' CView).

Si vous souhaitez arrêter ces règles, vous devez substituer la méthode d' PostNcDestroy de votre classe dérivée.Pour ajouter l'automobile-CleanUp à votre classe, appelez votre classe de base puis faites delete this.Pour supprimer l'automobile-CleanUp de votre classe, appelez CWnd::PostNcDestroy directement au lieu de la méthode d' PostNcDestroy de votre classe de base directe.

Le plus souvent utilisés de modifier le comportement automatique de nettoyage est de créer une boîte de dialogue non modale qui peut être allouée sur le tas.

Lorsque appeler delete

Nous vous recommandons d'appeler DestroyWindow pour détruire un objet de windows, la méthode C++ ou l'API générale d' DestroyWindow .

N'appelez pas l'API générale d' DestroyWindow pour détruire une fenêtre enfant MDI.Vous devez utiliser la méthode virtuelle CWnd::DestroyWindow à la place.

Pour les objets window C++ qui n'exécutent pas l'automobile-CleanUp, à l'aide de l'opérateur d' delete peut entraîner une fuite de mémoire lorsque vous essayez d'appeler DestroyWindow dans le destructeur d' CWnd::~CWnd si le VTBL n'indique pas la classe correctement dérivée.Cela est dû au fait que le système ne trouve pas le approprié destroy la méthode à appeler.À l'aide de DestroyWindow au lieu d' delete éviter ces problèmes.Étant donné que cela peut être une erreur subtile, compiler en mode débogage génère l'avertissement suivant si vous êtes confronté.

Warning: calling DestroyWindow in CWnd::~CWnd
   OnDestroy or PostNcDestroy in derived class will not be called

Dans le cas de les objets de fenêtres C++ qui affectent l'automobile-CleanUp, vous devez appeler DestroyWindow.Si vous utilisez l'opérateur d' delete directement, l'allocateur de mémoire de diagnostic MFC vous avertit que vous libérez la mémoire deux fois.Les deux occurrences sont votre premier appel explicite et l'appel indirect à delete this dans l'implémentation d'automobile-CleanUp d' PostNcDestroy.

Après avoir appelé DestroyWindow sur un objet de non-automobile-CleanUp, l'objet C++ sera toujours utilisateurs, mais m_hWnd sera NULL.Après avoir appelé DestroyWindow sur un objet d'automobile-CleanUp, l'objet C++ est allé, récupéré par l'opérateur delete C++ dans l'implémentation d'automobile-CleanUp d' PostNcDestroy.

Voir aussi

Autres ressources

Notes techniques de nombres

Notes techniques de catégorie