TN017: Destruir janela objetos

Esta anotação descreve o uso da função de membro CWnd::PostNcDestroy . Use esta função se você desejar fazer alocação personalizada de CWnd-derivado objetos.

Esta nota também explica algumas das razões para a regra cardinal:

Para destruir um objeto C++ Windows, use DestroyWindow não "excluir".

Isso é importante. Se você seguir as orientações abaixo, você terá alguns problemas de limpeza (como esquecer de excluir/liberar memória de C++, esquecendo-se de liberar recursos do sistema como o HWNDs ou liberando objetos muitas vezes).

O problema

Windows objetos (objetos de classes derivadas de CWnd) representam um objeto C++ (alocados no heap do aplicativo) e um HWND (alocados em recursos do sistema pelo Gerenciador de janela). Uma vez que existem várias maneiras de destruir um objeto janela, temos de dar um conjunto de regras que impedir o recurso de sistema ou vazamentos de memória de aplicativo e que impedir que objetos e alças Windows sendo destruída mais de uma vez.

Isso é mais do que um problema de gerenciamento de memória. A presença de uma janela do Windows tem impacto de interface do usuário: uma janela desenhada na tela; uma vez que ele é destruído há também um impacto nos recursos do sistema. Vazando memória de C++ em seu espaço de endereço de aplicativo não é tão mau como vazamento de recursos de sistema.

A destruição de Windows

São as duas maneiras permitidas para destruir um objeto do Windows:

O primeiro caso é de longe o mais comum. Neste caso aplica-se mesmo se DestroyWindow não é chamado diretamente pelo seu código. O é o caso quando o usuário diretamente fecha uma janela do quadro (o comportamento WM_CLOSE padrão é chamar DestroyWindow), e quando uma janela pai é destruída, o Windows chama DestroyWindow para todas as crianças.

O segundo caso, o uso do operador Excluir sobre objetos do Windows, deve ser muito raro e somente nos casos descritos abaixo.

Limpeza automática com CWnd::PostNcDestroy

Ao destruir uma janela do Windows, a última mensagem Windows enviada para a janela é WM_NCDESTROY. O manipulador usar como padrão CWnd para essa mensagem (CWnd::OnNcDestroy) vai destacar o HWND do objeto C++ e chamada de que 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 janela objetos alocados no quadro de pilha ou incorporados em outros objetos. Isso não é adequado para objetos de janela que são projetados para ser alocado por si mesmos no heap (não incorporado em outro objeto de C++).

Essas classes são projetadas para ser alocado por si mesmos no heap substituem a função de membro PostNcDestroy para realizar uma "Excluir este". Esta declaração será livre qualquer memória de C++ associado com o objeto C++. Mesmo que o destruidor de CWnd padrão chama DestroyWindow se m_hWnd é não-NULL, isso não levar a recursão infinita desde o identificador será desanexado e nulo durante a fase de limpeza.

&Notanbsp;CWnd::PostNcDestroy normalmente é chamado após o Windows WM_NCDESTROY mensagem é processada, como parte da destruição de janela, e o HWND e o objeto de janela de C++ não estão conectados. CWnd::PostNcDestroy também será chamado na execução da maioria das chamadas de criar se ocorrer uma falha (veja abaixo para regras de limpeza automática).

Classes de limpeza auto

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

As seguintes classes são projetadas para limpeza automática. Eles são normalmente atribuídos por si mesmos no heap:

Se você deseja quebrar qualquer uma destas regras, você deve substituir a função de membro PostNcDestroy em sua classe derivada. Para adicionar auto-limpeza para sua classe, simplesmente chamar a classe base e, em seguida, fazer uma Excluir isso. Para remover a limpeza automática de sua classe, chamar CWnd::PostNcDestroy diretamente em vez do PostNcDestroy membro no seu classe base direta.

O uso mais comum de acima é para criar uma caixa de diálogo sem janela restrita que pode ser alocada no heap.

Quando a chamada 'Excluir'

A maneira recomendada para destruir um objeto do Windows é chamar DestroyWindow, quer a função de membro C++ ou o global :: DestroyWindow API.

Não chame o global :: DestroyWindow API para destruir uma janela filho MDI, use a função de membro virtual CWnd:: DestroyWindow.

Para objetos de janela de C++ que não realizar auto-limpeza, uso DestroyWindow em vez de Excluir evita problemas de ter que chamar DestroyWindow CWnd:: ~ CWnd destruidor onde VTBL não está apontando para a classe derivada corretamente. Isso pode levar a erros sutis para a versão de diagnóstico (Depurar) do MFC irá avisá-lo com

Aviso: chamar DestroyWindow em CWnd:: ~ CWnd
 nbsp; OnDestroy ou Post&NcDestroy na classe derivada não será chamado

No caso de objetos do Windows C++ que realizar auto-limpeza, você deve chamar DestroyWindow. Se você usar operador Excluir diretamente, o alocador de memória diagnóstico do MFC irá alertá-lo a que estão liberando memória duas vezes (a primeira chamada para Excluir ), bem como a chamada indireta para "Excluir este" na implementação de limpeza automática de PostNcDestroy.

Depois de chamar DestroyWindow em um objeto não-auto-limpeza, o objeto C++ será ainda ao redor, mas m_hWnd será NULL. Depois de chamar DestroyWindow em um objeto de auto-limpeza, o objeto C++ será ido, liberada pelo C++ excluir operador na aplicação de auto-limpeza do PostNcDestroy..

Técnico anotações por número |nbsp; &Notas técnicas por categoria

Index