此附注描述支援將 Windows 物件句柄對應至C++物件的 MFC 例程。
問題
Windows 物件通常以各種 HANDLE 物件表示。MFC 類別會將 Windows 物件的句柄包裝成 C++ 物件。 MFC 類別庫的句柄包裝函式可讓您找到包裝具有特定句柄之 Windows 物件的C++物件。 不過,有時候對象沒有C++包裝函式物件,而此時系統會建立暫存物件來做為C++包裝函式。
使用句柄對應的 Windows 物件如下所示:
HWND (CWnd 和
CWnd衍生類別)HDC (CDC 和
CDC衍生類別)HMENU (CMenu)
HPEN (CGdiObject)
HBRUSH (
CGdiObject)HFONT (
CGdiObject)HBITMAP (
CGdiObject)HPALETTE (
CGdiObject)HRGN (
CGdiObject)HIMAGELIST (CImageList)
SOCKET (CSocket)
為任一物件指定句柄,您可以藉由呼叫靜態方法 FromHandle來尋找包裝句柄的 MFC 物件。 例如,假設 HWND 名為 hWnd,下列這一行會傳回包裝 CWnd 的指標:
CWnd::FromHandle(hWnd)
如果 hWnd 沒有特定的包裝函式物件,則會建立暫存 CWnd 專案來包裝 hWnd。 這可讓您從任何句柄取得有效的C++物件。
擁有包裝函式對象之後,您可以從包裝函式類別的公用成員變數擷取其句柄。 在 CWnd 的情況下,m_hWnd 包含該物件的 HWND。
將句柄附加至 MFC 物件
給定一個新建立的 handle-wrapper 物件和 Windows 物件的句柄,您可以呼叫Attach函數將兩者建立關聯,如下例所示:
CWnd myWnd;
myWnd.Attach(hWnd);
這會在永久映射中建立一個條目以連結 myWnd 和 hWnd。 現在呼叫 CWnd::FromHandle(hWnd) 將會傳回指向 myWnd 的指標。 刪除 myWnd 時,解構函式會藉由呼叫 Windows DestroyWindow 函式自動終結 hWnd。 如果這是不想要的,在 myWnd 被銷毀之前,hWnd 必須與 myWnd 中斷連結(通常是在離開定義 myWnd 的範圍時)。 方法 Detach 會執行此動作。
myWnd.Detach();
關於暫時物件的詳細資訊
每當 FromHandle 指定尚未具有包裝物件的句柄時,就會建立暫存物件。 這些暫存物件會從其句柄中斷連結,並由函式 DeleteTempMap 刪除。 預設情況下 CWinThread::OnIdle 會自動呼叫 DeleteTempMap 支援暫存句柄映射的每個類別。 這表示您無法假設指向暫時物件的指標在函式執行結束後仍然有效。
包裝函式物件和多個線程
臨時物件和永久物件都是以每個線程為基礎來管理。 也就是說,無論線程是暫時還是永久,一個線程都無法存取另一個線程的C++包裝函式物件。
若要將這些物件從一個線程傳遞至另一個線程,請一律將它們傳送為原生 HANDLE 類型。 將C++包裝函式物件從一個線程傳遞至另一個線程,通常會導致非預期的結果。