Win32 API 是 Windows 應用開發的基石,MFC 是其上層 C++ 封裝框架。本文嘗試以 UML/領域模型視角,系統梳理 Win32 API 核心概念:三大物件類別 (User/GDI/Kernel)、系統中斷轉訊息機制、視窗樹體系、訊息分類、視窗風格與類別,為深入理解 MFC 奠基。
┌─────────────────────────────────────┐
│ System (OS) │
│ 中斷 → 訊息封裝 → 投遞至 Thread MQ │
├─────────────────────────────────────┤
│ Kernel Objects │
│ File ←→ Module ←→ Process ←→ Thread │
│ (可執行檔) (至少一條 Thread) │
├─────────────────────────────────────┤
│ User Objects ◄─── 擁有者: Thread │
│ Window Tree (Desktop 為根) │
├─────────────────────────────────────┤
│ GDI Objects ◄─── 使用者: Thread │
│ DC (容器) ← SelectObject → BMP/Font │
└─────────────────────────────────────┘
關鍵點:
硬體中斷 (鍵盤/滑鼠/計時器/磁碟)
│
▼
核心中斷處理常式 (ISR)
│
▼
系統將中斷資訊封裝為 MSG 結構
│
▼
投遞至目標 Thread 的訊息佇列 (Message Queue)
│
▼
Thread 迴圈 GetMessage/DispatchMessage
│
▼
呼叫視窗程序 WindowProc (或 AfxWndProc)
SelectObject:放入 Bitmap/Brush/Pen/Font/Region/PathSelectPalette:放入 PaletteBeginPath/EndPath:放入 PathWindow Tree:
Desktop (根)
├─ Top-level Window (WS_OVERLAPPED / WS_POPUP)
│ ├─ Child Window (WS_CHILD)
│ │ └─ Child Window ...
│ └─ ...
└─ ...
每個節點記錄 4 指標:Parent、Child、Sibling (Brother)、Owner
HWND CreateWindow(
LPCTSTR lpClassName, // 窗口類別名 → 關聯 WNDCLASS
LPCTSTR lpWindowName, // 標題
DWORD dwStyle, // WS_OVERLAPPED/POPUP/CHILD 等
int x, y, w, h,
HWND hWndParent, // 父視窗 (Child 必填)
HMENU hMenu, // 選單/子視窗 ID
HINSTANCE hInstance, // 模組實例
LPVOID lpParam // 建立參數
);
關鍵:窗口類別 (WNDCLASS) 記錄 WindowProc、類別樣式、圖示、游標、背景筆刷、選單名、類別名
一個類別可對應多個視窗實例
模組 (hInstance) 是 WindowProc 與資源的「老家」
| 風格 | 本質分類 | 典型用途 | CreateWindow dwStyle |
|---|---|---|---|
| WS_OVERLAPPED | Top-level Window | 標準應用程式主視窗 | WS_OVERLAPPEDWINDOW (含標題、邊框、系統選單、最小/最大化) |
| WS_POPUP | Top-level Window (特殊 OVERLAPPED) | 對話框、工具視窗、無標題視窗 | WS_POPUP | WS_BORDER | WS_SYSMENU... |
| WS_CHILD | Child Window | 控件 (Button/Edit/List)、子視圖 | WS_CHILD | WS_VISIBLE | WS_BORDER... |
本質區別:
WS_CHILD:必須 有父視窗、座標相對父視窗客戶區、剪裁於父視窗內WS_OVERLAPPED:獨立顯示、座標為螢幕座標、可有擁有者 (Owner) 但非父視窗WS_POPUP:行為上屬於 WS_OVERLAPPED 特例,常用於對話框 (模態/非模態)Control (按鈕/編輯/列表) → 必須 WS_CHILD
Dialog (對話框) → 必須 WS_POPUP (通常 WS_POPUP | WS_CAPTION | WS_SYSMENU)
一般視窗 → 任意風格 (OVERLAPPED/POPUP/CHILD 視用途)
CreateDialog(hInst, MAKEINTRESOURCE(IDD_DIALOG), hWndParent, DlgProc);
差異:
1. 對話框模板資源 (DLGTEMPLATE) 定義佈局、控件位置/樣式/ID
2. 系統自動建立對話框視窗、載入模板建立子控件
3. 內部仍有窗口類別 (系統預定義 #32770)
4. 訊息處理:DlgProc 回調函數 (非 WindowProc),支援預設鍵盤導航 (Tab/Enter/Esc)
訊息來源:
├─ 系統產生 (硬體中斷 → WM_KEYDOWN, WM_MOUSEMOVE, WM_TIMER, WM_PAINT...)
└─ API 產生 (PostMessage/SendMessage → 自定義訊息 WM_USER+, WM_APP+)
每個訊息必須發送給特定視窗 (hWnd)
訊息佇列屬於 Thread,唯有 Thread 能接收/處理訊息
Win32 API 領域模型核心三大支柱:
理解「中斷→訊息→佇列→Thread→WindowProc」完整鏈路,以及視窗風格的本質分類 (CHILD vs OVERLAPPED/POPUP),是掌握 MFC 封裝邏輯 (CWnd::CreateEx, 訊息映射, 命令路由) 的必要前提。