Compartilhar via


TN017: destruindo objetos de janela

Essa observação descreve o uso do método de CWnd::PostNcDestroy . Use este método se você deseja fazer a alocação personalizado de CWnd- objetos derivados. Essa observe também explica como você deve usar CWnd::DestroyWindow destruir o windows para c criando objetos em vez do operador de delete .

Se você siga as diretrizes deste tópico, você terá alguns problemas de limpeza. Esses problemas podem resultar de problemas como o esquecimento excluir/memória livre C++, o esquecimento liberar recursos do sistema como HWNDs, ou liberar objetos muitas vezes.

O problema

Cada objeto do windows (objeto de uma classe derivada de ambos os CWnd) representa o objeto c criando e HWND. Os objetos C++ são atribuídos no heap de aplicativo e HWNDs é atribuído nos recursos do sistema pelo gerenciador de janela. Como há várias maneiras de destruir um objeto da janela, devemos fornecer um conjunto de regras que impedem o recurso do sistema ou os possíveis vazamentos de memória. Essas regras também devem evitar que os objetos e as alças do windows serem destruídos mais de uma vez.

Janelas de destruição

Os seguintes são as duas maneiras permitidas de destruir um objeto do windows:

  • CWnd::DestroyWindow chamada ou a API do windows DestroyWindow.

  • Excluindo explicitamente com o operador de delete .

Os primeiros casos são muito mais comuns. Esses casos se aplicam mesmo se seu código não chama DestroyWindow diretamente. Quando o usuário fecha diretamente uma janela do quadro, essa ação gerencia a mensagem de WM_CLOSE , e a resposta padrão para esta mensagem é chamar DestroyWindow. quando uma janela pai é destruída o windows, chama DestroyWindow para todos os seus filhos.

Os segundos casos, o uso do operador de delete no objeto, devem ser raros. Estes são alguns casos em que são delete usando a opção correta.

Auto clean-up com CWnd::PostNcDestroy

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

A implementação padrão de CWnd::PostNcDestroy não fará nada, que é apropriado para os objetos da janela que são atribuídos no quadro de pilhas ou inseridos em outros objetos. Isso não é apropriado para os objetos da janela que são criados para serem alocados no heap sem nenhum outros objetos. Em outras palavras não é apropriado para os objetos da janela que não são inseridos em outros objetos C++.

Essas classes que são projetadas para serem atribuídas na substituição de heap o método de PostNcDestroy para executar delete this. Essa instrução liberará toda a memória associada ao objeto C++. Mesmo que o destruidor de CWnd da opção exige DestroyWindowm_hWnd se for não NULL, isso não resulta na recursão infinita como o identificador será NULL e desanexada durante a fase de limpeza.

Dica

O sistema chama em geral CWnd::PostNcDestroy depois que processa a mensagem de WM_NCDESTROY do windows e HWND e o objeto da janela C++ está conectado não.O sistema também chamará CWnd::PostNcDestroy na implementação da maioria das chamadas de CWnd::Create se a falha.As regras de limpeza automática são descritas posteriormente neste tópico.

Classes de limpeza automática

As classes a seguir não são criadas para a limpeza automática. Normalmente são inseridos em outros objetos C++ ou na pilha:

  • Todos os controles do windows (padrão deCStatic, CEdit, CListBox, e assim por diante).

  • Algumas janelas filho derivadas diretamente de CWnd (por exemplo, controla personalizados).

  • Janelas de divisão (CSplitterWnd).

  • Barras de controle padrão (classes derivadas de CControlBar, consulte Observação 31 técnica para habilitar o automaticamente DELETE para objetos da barra de controle).

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

  • Todas as caixas de diálogo do padrão exceptuam CFindReplaceDialog.

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

As classes a seguir são criadas para a limpeza automática. São atribuídos normalmente específica no heap:

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

  • Janelas de exibição (derivadas diretamente ou indiretamente de CView).

Para interromper essas regras, você deve substituir o método de PostNcDestroy em sua classe derivada. Para adicionar a limpeza automática a sua classe, chame a sua classe base e faça delete this. Para remover a limpeza automática da sua classe, chame CWnd::PostNcDestroy diretamente em vez do método de PostNcDestroy da sua classe base direta.

O uso mais comum de alterar o comportamento automático de limpeza é criar uma caixa de diálogo modeless que pode ser atribuída no heap.

Quando chamar a exclusão

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

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

Para os objetos da janela C++ que não executam a limpeza automática, usar o operador de delete pode causar um vazamento de memória quando você tentar chamar DestroyWindow em destruidor de CWnd::~CWnd se o VTBL não aponta corretamente a classe derivada. Isso ocorre porque o sistema não pôde localizar o apropriado destrói o método para chamar. Usar DestroyWindow em vez de delete evitar esses problemas. Como esse pode ser um erro sutil, compile no modo de depuração gerará o seguinte aviso se você está em risco.

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

No caso de objetos do windows C++ que executa a limpeza automática, você deve chamar DestroyWindow. Se você usar o operador de delete diretamente, o alocador de diagnóstico de memória MFC notificá-lo-á que você está liberando memória duas vezes em. As duas ocorrências são seu primeiro chamada explícita e a chamada indireto a delete this na implementação de limpeza automática de PostNcDestroy.

Depois de chamar DestroyWindow em um objeto de não-automóvel- limpeza, o objeto do C++ ainda estará em relação a, mas m_hWnd será NULL. Depois de chamar DestroyWindow em um objeto de limpeza automática, o objeto será C++ ido, liberado pelo operador delete C++ na implementação de limpeza automática de PostNcDestroy.

Consulte também

Outros recursos

Observações técnicas por número

Observações técnicas por categoria