TN017 : Détruire les objets de la fenêtre

Cette note décrit l'utilisation de la fonction membre CWnd::PostNcDestroy . Utilisez cette fonction si vous souhaitez effectuer une allocation personnalisée de CWnd-objets dérivés.

Cette note explique aussi certains des motifs de la règle cardinale:

Pour détruire un objet C++ Windows, utilisez DestroyWindow pas « supprimer ».

C'est important. Si vous suivez les directives ci-dessous, vous aurez quelques problèmes de nettoyage (comme par exemple oublier de supprimer/libérer la mémoire de C++, oublier de libérer les ressources système comme HWNDs ou libérer des objets trop de fois).

Le problème

Windows objets (objets de classes dérivées de CWnd) représentent un objet C++ (alloué dans le tas de l'application) et en un HWND (attribué en ressources système par le gestionnaire de fenêtres). Puisqu'il y a plusieurs façons de détruire un objet window, nous devons fournir un ensemble de règles qui empêchent le système de ressources ou les fuites de mémoire de l'application et qui empêchent les objets et les poignées de fenêtres d'être détruit plus d'une fois.

C'est plus qu'un problème de gestion de mémoire. La présence d'une fenêtre de Windows a l'impact de l'interface utilisateur : une fenêtre sur l'écran ; une fois qu'il est détruit il y aussi un impact sur les ressources système. Fuites de mémoire de C++ en l'espace d'adressage de votre application ne sont pas aussi mauvaises que la fuite des ressources système.

Détruisant Windows

Les deux façons permises pour détruire un objet Windows sont:

Le premier cas est de loin la plus fréquente. Ce cas s'applique même si DestroyWindow n'est pas appelée directement par votre code. L'est le cas lorsque l'utilisateur ferme directement une fenêtre frame ( WM_CLOSE comportement par défaut consiste à appeler DestroyWindow), et quand une fenêtre parente est détruite, Windows appelle DestroyWindow pour tous les enfants.

Le deuxième cas, l'utilisation de l'opérateur delete sur des objets de Windows, doivent être très rare et seulement dans les cas décrits ci-dessous.

Nettoyage automatique avec CWnd::PostNcDestroy

Lors de la destruction d'une fenêtre de Windows, le dernier message de Windows à la fenêtre est WM_NCDESTROY. CWnd Gestionnaire par défaut pour ce message (CWnd::OnNcDestroy) vont se détacher le HWND de l'objet C++ et appel que virtuel fonction PostNcDestroy. Certaines classes substituer à cette fonction pour supprimer l'objet C++.

L'implémentation par défaut de CWnd::PostNcDestroy ne fait rien qui est appropriée pour les objets de la fenêtre allouée sur le frame de pile ou incorporées dans d'autres objets. Ce n'est pas approprié pour les objets de la fenêtre qui sont conçus pour être alloués par eux-mêmes sur le tas (ne pas incorporé dans autre objet C++).

Ces classes sont conçues pour être attribué par eux-mêmes sur le tas de substituent la fonction membre PostNcDestroy pour effectuer un "delete this". Cette déclaration va libérer de la mémoire associée à l'objet C++ C++. Même si le destructeur de CWnd par défaut appelle DestroyWindow si m_hWnd est non nulle, cela ne conduit pas à une récurrence infinie puisque la poignée sera détachée et NULL lors de la phase de nettoyage.

&Notenbsp ;CWnd::PostNcDestroy est normalement appelé après les fenêtres WM_NCDESTROY message est traité, dans le cadre de la destruction de la fenêtre, et le HWND et l'objet de fenêtre C++ sont attachés n'est plus. CWnd::PostNcDestroy sera également appelé à la mise en œuvre de la plupart des appels de créer si un échec se produit (voir ci-dessous pour les règles de nettoyage automatique).

Classes de nettoyage auto

Les classes suivantes ne sont pas conçus pour le nettoyage de l'auto. Ils sont normalement intégrés dans un autre objet C++ ou sur la pile:

Les classes suivantes sont conçues pour auto-nettoyage. Ils sont normalement alloués par eux-mêmes sur le tas:

Si vous souhaitez briser une de ces règles, vous devez substituer la fonction membre PostNcDestroy dans votre classe dérivée. Ajouter auto-nettoyage de votre classe, appelez simplement votre classe de base et ensuite faire un delete this. Pour supprimer des auto-nettoyage de votre classe, composez le CWnd::PostNcDestroy directement au lieu du membre PostNcDestroy dans votre classe de base directe.

L'utilisation la plus courante de ce qui précède est de créer une boîte de dialogue non modale qui peut être alloué sur le tas.

Quand à l'appel « delete »

La méthode recommandée pour détruire un objet Windows consiste à appeler DestroyWindow, soit la fonction membre C++ ou le global :: DestroyWindow API.

N'appelez pas le global :: DestroyWindow API de détruire une fenêtre enfant MDI, utilisez la fonction membre virtuelle CWnd::DestroyWindow plutôt.

Pour les objets de la fenêtre C++ qui n'exécutent pas auto-nettoyage, au lieu de Supprimer à l'aide de DestroyWindow évite les problèmes d'avoir à appeler DestroyWindow dans la CWnd:: ~ CWnd destructeur où le VTBL ne pointe pas à la classe dérivée correctement. Cela peut conduire à des bogues subtils pour la version de diagnostic (débogage) des MFC vous avertira

Avertissement : appel à DestroyWindow dans CWnd:: ~ CWnd
 nbsp ; OnDestroy ou Post&NcDestroy dans la classe dérivée ne sera pas appelée

Dans le cas d'objets C++ Windows exécuter auto-nettoyage, vous devez appeler DestroyWindow. Si vous utilisez opérateur Supprimer directement, l'allocateur de mémoire de diagnostic MFC vous avertiront que vous sont libérer de mémoire deux fois (le premier appel à Supprimer ) ainsi que l'appel indirect à "supprimer ce" dans la mise en œuvre auto-nettoyage de PostNcDestroy.

Après l'appel à DestroyWindow sur un objet non-auto-nettoyage, l'objet C++ seront toujours autour, mais m_hWnd sera NULL. Après l'appel à DestroyWindow sur un objet d'auto-nettoyage, l'objet C++ aura disparu, libéré par l'opérateur delete C++ dans la mise en œuvre auto-nettoyage de PostNcDestroy..

&Notes techniques par le numéro |nbsp ; Notes techniques par catégorie

Index