MFC 核心價值在於將 Win32 API 以 C++ 類別封裝。理解 MFC 物件(C++ 實例)與 Windows 物件(核心物件,由句柄標識) 的對應、生命週期差異與轉換方式,是高效開發的基石。
| 維度 | MFC 物件 (CWnd 衍生類實例) | Windows 物件 (HWND) |
|---|---|---|
| 資料結構 | C++ 類別實例,含成員變數 m_hWnd | 系統內部資料結構,由句柄引用 |
| 層級 | 高層封裝,提供成員函式操作 | 低層核心物件,需呼叫 SDK API |
| 創建 | 兩階段:建構子 → Create() 呼叫 SDK 創建視窗並存入 m_hWnd | 由 CreateWindowEx 等 SDK 函式創建 |
| 轉換 | GetSafeHandle() 取得句柄;FromHandle()/Attach() 從句柄建立/關聯 MFC 物件 | 句柄在進程間全域可見,可跨進程傳遞 |
| 銷毀 | 解構子呼叫;GDI 物件可能只是釋放而非銷毀 | 需呼叫對應 SDK 函式(如 DestroyWindow) |
| 可見範圍 | 僅本進程、本執行緒可用 | 系統全域可見,跨進程可用 |
| 描述 | Windows 句柄 | MFC 類別 |
|---|---|---|
| 視窗 | HWND | CWnd 及衍生類 |
| 裝置內容 | HDC | CDC 及衍生類 |
| 選單 | HMENU | CMenu |
| 筆刷/字體/位圖/調色板/區域 | HPEN/HBRUSH/HFONT/HBITMAP/HPALETTE/HRGN | CGdiObject → CPen/CBrush/CFont/CBitmap/CPalette/CRgn |
| 影像清單 | HIMAGELIST | CImageList |
| 通訊端 | SOCKET | CSocket/CAsyncSocket |
廣義上,CDocument 與檔案句柄也可視為一對。
SDK 開發需手動填寫 WNDCLASSEX 並呼叫 RegisterClassEx。MFC 提供多種註冊途徑:
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass) {
// 1. 檢查是否已註冊(原子表查詢)
// 2. 呼叫 ::RegisterClass(lpWndClass)
// 3. 若為 DLL 模組,將類別名加入模組狀態 m_szUnregisterList,以便卸載時自動註銷
}
MFC 內建註冊常用類別(如 _afxWnd、_afxFrame、_afxMDIFrame、_afxControlBar 等),儲存於模組狀態 AFX_MODULE_STATE 的 m_classList 鏈表中,AfxEndDeferRegisterClass 於程式結束時統一註銷。
允許開發者自訂 WNDCLASS 參數(如自訂背景筆刷、游標、圖示),內部同樣呼叫 AfxRegisterClass。
MFC 使用 AFX_MODULE_STATE 維護每個模組(EXE/DLL)獨立的類別註冊清單、資源鏈狀態等。_AFXDLL 定義控制巨集展開差異,確保跨 DLL 邊界時類別資訊正確隔離與共享。