Compartilhar via


TN017: Destruição de objetos de janela

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

Se você seguir as diretrizes neste tópico, você terá alguns problemas de limpeza.Esses problemas podem resultar de problemas, sistema autônomo esquecer de excluir / memória disponível C++, esquecer de disponível recursos do sistema, sistema autônomo HWNDsistema autônomo ou disponível ing objetos várias vezes.

O problema

Cada objeto de janelas (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 são alocados os recursos do sistema pelo Gerenciador de janela. Como existem várias maneiras para destruir um objeto de janela, deve fornecer um conjunto de regras que impedem que o sistema vazamentos de memória ou recursos.Essas regras devem também impedir que objetos e as alças do Windows sendo destruído a mais de uma vez.

Destruindo Windows

As duas maneiras permitidas para destruir um objeto do Windows são:

  • De chamadaCWnd::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 que seu código não telefonar DestroyWindow diretamente. Quando o usuário diretamente fecha uma janela do quadro, essa ação gera o WM_CLOSE mensagem e a resposta padrão para esta mensagem é telefonar DestroyWindow. When a parent window is destroyed, Windows calls DestroyWindow for all its children.

O segundo caso, o uso do delete operador de objetos do Windows, devem ser raros. O seguir são alguns casos onde usando delete é a opção correta.

Limpeza automática com CWnd::PostNcDestroy

Quando o sistema destruir uma janela do Windows, a mensagem Windows última enviada para a janela é WM_NCDESTROY. O padrão de CWnd o manipulador para essa mensagem é CWnd::OnNcDestroy. OnNcDestroy irá desanexar o HWND do objeto C++ e telefonar a função virtual PostNcDestroy. Algumas classes substituir 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 em registro de ativação ou incorporados em outros objetos. Isso não é adequado para objetos de janela são projetados para ser alocada no heap sem quaisquer 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 sozinho alocado na heap de substituem o PostNcDestroy método para executar uma delete this. Essa demonstrativo liberará toda a memória associada ao objeto C++.Embora o padrão de CWnd chamadas de destruidor DestroyWindow Se m_hWnd é não-nulo, isso não levar a recursão infinita porque o identificador será desanexado e nulo durante a fase de limpeza.

Observação:

O sistema normalmente chama CWnd::PostNcDestroy Após o Windows processa WM_NCDESTROY mensagem e o HWND e o objeto da janela C++ não estão conectados. O sistema também irá chamar CWnd::PostNcDestroy na implementação de mais CWnd::criar a telefonar se ocorrer falha. As regras de limpeza automática são descritas neste tópico.

Classes de limpeza automática

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

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

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

  • Divisor de janelas (CSplitterWnd).

  • Barras de controle padrão (classes derivadas de CControlBar, consulte Observação técnica 31 para habilitar excluir automática para objetos de BAR de controle).

  • Caixas de diálogo (CDialog) projetado para caixas de diálogo modais na estrutura de pilhas.

  • Todas as caixas de diálogo padrão, exceto CFindReplaceDialog.

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

As classes a seguir destinam-se a limpeza automática.Eles geralmente são alocados pelo próprios na pilha:

  • Janelas de quadro principal (derivadas direta ou indiretamente de CFrameWnd).

  • Modo de exibição de janelas (derivadas direta ou indiretamente de CView).

Se você deseja quebrar essas regras, você deve substituir o PostNcDestroy método em sua classe derivada. Limpeza automática de adicionar à sua classe, chamar sua classe base e, em seguida, fazer um delete this. Para remover a limpeza automática da sua classe, telefonar CWnd::PostNcDestroy diretamente em vez da 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 telefonar de excluir

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

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

Para objetos de janela de C++ que não executam a limpeza automática, usando o delete operador pode causar um perda de memória ao tentar telefonar DestroyWindow no CWnd::~CWnd Destrutor se o VTBL não aponta para a classe derivada corretamente. Isso ocorre porque o sistema não pode localizar o apropriado método para destruir telefonar.Usando DestroyWindow em vez de delete evita a esses problemas. Como isso pode ser um erro sutil, compilando no modo de depurar gerará o seguinte aviso se você estiver 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 telefonar DestroyWindow. Se você usar o delete o operador diretamente, o alocador de diagnóstico de memória MFC avisará que você está liberando memória duas vezes. Duas ocorrências são a primeira telefonar explícita e a telefonar indireta delete this na implementação de limpeza automática PostNcDestroy.

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

Consulte também

Outros recursos

Notas técnicas por número

Notas técnicas por categoria