Partilhar via


TN003: mapeamento de identificadores do Windows para objetos

Esta observação descreve as rotinas MFC que dão suporte ao mapeamento de identificadores de objeto do Windows para objetos C++.

O problema

Objetos do Windows normalmente são representados por vários objetos HANDLE As classes MFC encapsulam identificadores de objeto do Windows com objetos C++. As funções de encapsulamento do identificador da biblioteca de classes MFC permitem que você encontre o objeto C++ que está encapsulando o objeto Windows que tem um identificador específico. No entanto, às vezes, um objeto não tem um objeto wrapper C++; nesses casos, o sistema cria um objeto temporário para atuar como o wrapper C++.

Os objetos do Windows que usam mapas de identificador são os seguintes:

  • HWND (classes derivadas de CWnd e CWnd)

  • HDC (classes derivadas de CDC e CDC)

  • HMENU (CMenu)

  • HPEN (CGdiObject)

  • HBRUSH (CGdiObject)

  • HFONT (CGdiObject)

  • HBITMAP (CGdiObject)

  • HPALETTE (CGdiObject)

  • HRGN (CGdiObject)

  • HIMAGELIST (CImageList)

  • SOCKET (CSocket)

Considerando um identificador para qualquer um desses objetos, você pode encontrar o objeto MFC que encapsula o identificador chamando o método estático FromHandle. Por exemplo, dado um HWND chamado hWnd, a seguinte linha retornará um ponteiro para o CWnd que encapsula hWnd:

CWnd::FromHandle(hWnd)

Se hWnd não tiver um objeto wrapper específico, um CWnd temporário será criado para encapsular hWnd. Isso possibilita obter um objeto C++ válido de qualquer identificador.

Quando você tiver um objeto wrapper, poderá recuperar seu identificador de uma variável de membro público da classe wrapper. No caso de um CWnd, m_hWnd contém o HWND para esse objeto.

Como anexar identificadores a objetos MFC

Dado um objeto handle-wrapper que acaba de ser criado e um identificador para um objeto do Windows, você pode associar os dois chamando a função Attach como neste exemplo:

CWnd myWnd;
myWnd.Attach(hWnd);

Isso faz com que uma entrada no mapa permanente associe myWnd e hWnd. Chamar CWnd::FromHandle(hWnd) agora retornará um ponteiro para myWnd. Quando myWnd é excluído, o destruidor destruirá automaticamente hWnd chamando a função DestroyWindow do Windows. Se isso não for desejado, hWnd deverá ser desanexado do myWnd antes que myWnd seja destruído (normalmente ao deixar o escopo no qual myWnd foi definido). O método Detach faz isso.

myWnd.Detach();

Mais sobre objetos temporários

Objetos temporários são criados sempre que FromHandle recebe um identificador que ainda não tem um objeto wrapper. Esses objetos temporários são desanexados do identificador e excluídos pelas funções DeleteTempMap. Por padrão, CWinThread::OnIdle chama DeleteTempMap automaticamente para cada classe que dá suporte a mapas de identificador temporários. Isso significa que você não pode presumir que um ponteiro para um objeto temporário será válido após o ponto de saída da função em que o ponteiro foi obtido.

Objetos wrapper e vários threads

Os objetos temporários e permanentes são mantidos por thread. Ou seja, um thread não pode acessar objetos de wrapper C++ de outro thread, seja ele temporário ou permanente.

Para passar esses objetos de um thread para outro, sempre envie-os como seu tipo nativo HANDLE. Passar um objeto wrapper C++ de um thread para outro em geral causará resultados inesperados.

Confira também

Observações técnicas por número
Observações técnicas por categoria