TN003: mapping di handle di finestre a oggetti
Questa nota descrive le routine MFC che supportano il mapping degli handle di oggetti Windows agli oggetti C++.
Problema
Gli oggetti Windows sono in genere rappresentati da vari oggetti HANDLE Le classi MFC eseguono il wrapping degli handle di oggetti Windows con oggetti C++. Le funzioni di wrapping dell'handle della libreria di classi MFC consentono di trovare l'oggetto C++ che esegue il wrapping dell'oggetto Windows con un handle specifico. Tuttavia, a volte un oggetto non dispone di un oggetto wrapper C++ e in questi casi il sistema crea un oggetto temporaneo da usare come wrapper C++.
Gli oggetti Windows che usano mappe handle sono i seguenti:
HWND (classi CWnd e
CWnd
derivate)HDC (classi CDC e
CDC
derivate)HMENU (CMenu)
HPEN (CGdiObject)
HBRUSH (
CGdiObject
)HFONT (
CGdiObject
)HBITMAP (
CGdiObject
)HPALETTE (
CGdiObject
)HRGN (
CGdiObject
)HIMAGELIST (CImageList)
SOCKET (CSocket)
Dato un handle a uno di questi oggetti, è possibile trovare l'oggetto MFC che esegue il wrapping dell'handle chiamando il metodo FromHandle
statico . Ad esempio, dato un HWND denominato hWnd, la riga seguente restituirà un puntatore all'oggetto CWnd
che esegue il wrapping di hWnd:
CWnd::FromHandle(hWnd)
Se hWnd non dispone di un oggetto wrapper specifico, viene creato un oggetto temporaneo CWnd
per eseguire il wrapping di hWnd. In questo modo è possibile ottenere un oggetto C++ valido da qualsiasi handle.
Dopo aver creato un oggetto wrapper, è possibile recuperarne l'handle da una variabile membro pubblica della classe wrapper. Nel caso di un CWnd
oggetto , m_hWnd contiene HWND per tale oggetto.
Associazione di handle a oggetti MFC
Dato un oggetto handle-wrapper appena creato e un handle a un oggetto Windows, è possibile associare i due chiamando la Attach
funzione come in questo esempio:
CWnd myWnd;
myWnd.Attach(hWnd);
In questo modo viene inserita una voce nella mappa permanente associando myWnd e hWnd. La chiamata CWnd::FromHandle(hWnd)
restituirà ora un puntatore a myWnd. Quando myWnd viene eliminato, il distruttore eliminerà automaticamente hWnd chiamando la funzione Windows DestroyWindow . Se questo non è desiderato, hWnd deve essere scollegato da myWnd prima che myWnd venga eliminato definitivamente (in genere quando si esce dall'ambito in cui è stato definito myWnd ). Il Detach
metodo esegue questa operazione.
myWnd.Detach();
Altre informazioni sugli oggetti temporanei
Gli oggetti temporanei vengono creati ogni volta FromHandle
che viene assegnato un handle che non dispone già di un oggetto wrapper. Questi oggetti temporanei vengono scollegati dal relativo handle ed eliminati dalle DeleteTempMap
funzioni. Per impostazione predefinita , CWinThread::OnIdle chiama DeleteTempMap
automaticamente per ogni classe che supporta le mappe di handle temporanee. Ciò significa che non è possibile presupporre che un puntatore a un oggetto temporaneo sia valido oltre il punto di uscita dalla funzione in cui è stato ottenuto il puntatore.
Oggetti wrapper e più thread
Gli oggetti temporanei e permanenti vengono mantenuti per ogni thread. Ovvero, un thread non può accedere agli oggetti wrapper C++ di un altro thread, indipendentemente dal fatto che sia temporaneo o permanente.
Per passare questi oggetti da un thread a un altro, inviarli sempre come tipo nativo HANDLE
. Il passaggio di un oggetto wrapper C++ da un thread a un altro causerà spesso risultati imprevisti.