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.