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