TN003:將 Windows 控制代碼對應到物件
此附注描述支援將 Windows 物件控制碼對應至 C++ 物件的 MFC 常式。
問題
Windows 物件通常以各種 HANDLE 物件表示。MFC 類別會使用 C++ 物件包裝 Windows 物件控制碼。 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 ,下列這一行會傳回包裝 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++ 包裝函式物件從一個執行緒傳遞至另一個執行緒,通常會導致非預期的結果。