Partilhar via


TN003: Mapeamento de handles do Windows para objetos

Observação

A biblioteca Microsoft Foundation Classes (MFC) continua a ser suportada. No entanto, já não estamos a adicionar funcionalidades nem a atualizar a documentação.

Esta nota descreve as rotinas MFC que suportam o mapeamento de identificadores de objetos do Windows para objetos C++.

O problema

Os objetos do Windows são normalmente representados por vários objetos HANDLE As classes MFC encapsulam identificadores de objeto do Windows com objetos C++. As funções de encapsulamento de handle da biblioteca de classes MFC permitem encontrar o objeto C++ que está a encapsular o objeto do Windows com um handle específico. No entanto, às vezes um objeto não tem um objeto wrapper C++ e, nesses momentos, 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 (CWnd e CWndclasses derivadas)

  • HDC (CDC e classes derivadas CDC)

  • HMENU (CMenu)

  • HPEN (CGdiObject)

  • HBRUSH (CGdiObject)

  • HFONT (CGdiObject)

  • HBITMAP (CGdiObject)

  • HPALETTE (CGdiObject)

  • HRGN (CGdiObject)

  • HIMAGELIST (CImageList)

  • SOCKET (CSocket)

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

CWnd::FromHandle(hWnd)

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

Depois de teres um objeto wrapper, podes recuperar o seu identificador a partir de uma variável membro pública da classe wrapper. No caso de um CWnd, m_hWnd contém o HWND para esse objeto.

Anexando alças a objetos MFC

Dado um objeto wrapper recém-criado e um identificador para um objeto do Windows, é possível associar os dois chamando a função Attach, como no exemplo a seguir:

CWnd myWnd;
myWnd.Attach(hWnd);

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

myWnd.Detach();

Mais sobre objetos temporários

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

Objetos de envoltório e múltiplos threads

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

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

Ver também

Notas técnicas por número
Notas técnicas por categoria