TN017: Destruir janela objetos

Esta anotação descreve o uso de CWnd::PostNcDestroy método.Use este método se você deseja fazer alocação personalizada de CWnd-derivado de objetos.Esta nota também explica por que você deve usar CWnd::DestroyWindow para destruir um objeto C++ Windows em vez do delete operador.

Se você seguir as diretrizes neste tópico, você terá alguns problemas de limpeza.Esses problemas podem resultar de problemas como esquecer de excluir/liberar memória do C++, esquecer de liberar recursos do sistema como HWNDs ou liberando objetos muitas vezes.

O problema

Cada objeto do windows (objeto de uma classe derivada de CWnd) representa um objeto de C++ e um HWND.Objetos C++ são alocados no heap do aplicativo e HWNDs recursos de sistema são alocados pelo Gerenciador de janela.Como existem várias maneiras de destruir um objeto de janela, devemos fornecer um conjunto de regras que impedem que o sistema de vazamentos de memória ou recursos.Essas regras também devem evitar Windows controla e objetos sejam destruídos mais de uma vez.

Destruindo o Windows

A seguir estão maneiras permitidas para destruir um objeto do Windows:

  • Chamando CWnd::DestroyWindow ou a API do Windows DestroyWindow.

  • Excluindo explicitamente com o delete operador.

O primeiro caso é de longe o mais comum.Neste caso se aplica mesmo se seu código não chama DestroyWindow diretamente.Quando o usuário diretamente fecha uma janela do quadro, essa ação gera a WM_CLOSE mensagem e a resposta padrão para essa mensagem é chamar DestroyWindow. quando uma janela pai é destruída, o Windows chama DestroyWindow para todos os seus filhos.

O segundo caso, o uso da delete operador de objetos do Windows devem ser raros.A seguir estão alguns casos onde usar delete a opção correta.

Limpeza automática com CWnd::PostNcDestroy

Quando o sistema destrói uma janela do Windows, a última mensagem do Windows enviada para a janela é WM_NCDESTROY.O padrão CWnd manipulador para a mensagem é CWnd::OnNcDestroy.OnNcDestroyirá desanexar o HWND C++ de objeto e chamar a função virtual PostNcDestroy.Algumas classes substituem esta função para excluir o objeto C++.

A implementação padrão de CWnd::PostNcDestroy não faz nada, que é apropriado para objetos de janela que são alocados no quadro de pilha ou incorporados em outros objetos.Não é apropriado para objetos de janela são projetados para ser alocada no heap sem outros objetos.Em outras palavras, não é apropriado para objetos de janela que não são incorporados em outros objetos do C++.

Essas classes são projetadas para ser alocado sozinho no heap substituem o PostNcDestroy método para executar um delete this.Esta instrução será livre qualquer memória associada ao objeto C++.Embora o padrão CWnd destruidor chamadas DestroyWindow se m_hWnd é nula, isso não levar a recursão infinita porque o identificador será desanexado e nulo durante a fase de limpeza.

ObservaçãoObservação

O sistema normalmente chama CWnd::PostNcDestroy depois que o Windows processa WM_NCDESTROY mensagem e o HWND e o objeto de janela C++ não está mais conectado.O sistema também irá chamar CWnd::PostNcDestroy na implementação das mais CWnd::Create chama se ocorrer falha.As regras de limpeza automática são descritas posteriormente neste tópico.

Classes de limpeza automática

As seguintes classes não são projetadas para a limpeza automática.Eles geralmente são incorporados em outros objetos C++ ou na pilha:

  • Todos os controles padrão do Windows (CStatic, CEdit, CListBoxe assim por diante).

  • Todas as janelas filho derivada diretamente de CWnd (por exemplo, controles personalizados).

  • Windows divisor (CSplitterWnd).

  • Padrão de barras de controle (classes derivadas de CControlBar, consulte técnico anotação 31 para ativar a exclusão automática para objetos de barra de controle).

  • Caixas de diálogo (CDialog) projetado para caixas de diálogo modais no quadro de pilha.

  • O padrão todos os diálogos exceto CFindReplaceDialog.

  • As caixas de diálogo padrão criadas por ClassWizard.

As classes a seguir destinam-se a limpeza automática.Eles geralmente são alocados por si na pilha:

  • Windows de quadro principal (derivada direta ou indiretamente de CFrameWnd).

  • Exibir windows (derivado direta ou indiretamente de CView).

Se você deseja quebrar essas regras, você deve substituir o PostNcDestroy método na sua classe derivada.Para adicionar a limpeza automática para sua classe, chamada de classe base e faça um delete this.Para remover a limpeza automática de sua classe, chamada CWnd::PostNcDestroy diretamente em vez do PostNcDestroy método de sua classe base direta.

O uso mais comum de alterar o comportamento de limpeza automática é criar uma caixa de diálogo sem janela restrita que pode ser alocada no heap.

Quando a chamada delete

Recomendamos que você chamar DestroyWindow para destruir um objeto do Windows, o método de C++ ou o global DestroyWindow API.

Não chame o global DestroyWindow API para destruir uma janela filho MDI.Você deve usar o método virtual CWnd::DestroyWindow em vez disso.

Para a janela de C++ objetos que não execute a limpeza automática, usando o delete operador pode causar um vazamento de memória quando você tentar chamar DestroyWindow na CWnd::~CWnd destruidor se o VTBL não aponta para a classe derivada corretamente.Isso ocorre porque o sistema não consegue localizar que o apropriado método chamar destruir.Usando DestroyWindow em vez de delete evita esses problemas.Como isso pode ser um erro sutil, compilando no modo de depuração gera o seguinte aviso se estão em risco.

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

No caso de objetos de C++ Windows executar limpeza automática, você deve chamar DestroyWindow.Se você usar o delete operador diretamente, o alocador de diagnóstico de memória do MFC avisará que você está liberando memória duas vezes.Duas ocorrências são sua primeira chamada explícita e indireta chamada para delete this na implementação de limpeza automática de PostNcDestroy.

Depois de chamar o DestroyWindow em um objeto de limpeza não automática, o objeto C++ continuará, mas m_hWnd será NULL.Depois de chamar o DestroyWindow um objeto de limpeza automática, o objeto C++ será desapareceu e liberada pelo operador delete C++ na implementação de limpeza automática de PostNcDestroy.

Consulte também

Outros recursos

Notas técnicas por número

Notas técnicas por categoria