模式對話框本質
- 也是視窗,可接收訊息、移動、關閉、繪圖;
- 阻塞:關閉前用戶無法操作同應用程式其他視窗;
- 編程模型簡單:
DoModal() 封裝完整訊息迴圈。
建立模式對話框四步驟
- 資源編輯器設計對話框 + 控件,自動更新
.rc 與 resource.h;
- ClassWizard 產生
CDialog 衍生類並關聯資源 ID (枚舉常量 IDD);
- ClassWizard 添加控件訊息響應函數 (BN_CLICKED, EN_CHANGE 等);
- 使用處:
CMyDlg dlg; dlg.DoModal(); // 阻塞直到結束
對話框啟動與關閉序列
DoModal()
→ OnInitDialog() // 使用者初始化
→ CDialog::OnInitDialog() // 基類初始化
→ UpdateData(FALSE) // 類成員 → 控件
→ DoDataExchange() // DDX/DDV 實際傳輸
... 用戶操作 ...
→ OnOK() // 使用者確認邏輯
→ CDialog::OnOK() // 基類確認
→ UpdateData(TRUE) // 控件 → 類成員
→ DoDataExchange()
→ EndDialog(IDOK) // 結束模態迴圈
DDX/DDV 核心
UpdateData(FALSE):初始化對話框 (成員→控件);
UpdateData(TRUE):回寫並驗證 (控件→成員);
DoDataExchange(CDataExchange* pDX):
DDX_Text(pDX, IDC_EDIT, m_str);
DDV_MaxChars(pDX, m_str, 20);
通用控件操作速查
| 控件 | 關鍵屬性/風格 | 常用操作 |
| Combo Box | Simple / Dropdown / Drop List | Data 頁加項目 Ctrl+Enter 換行 |
| List Box | 單選、排序 | 設計時不可預設選項 |
| Static Text | 含 & 字元 (如 &Name) | Alt+熱鍵跳轉,同一對話框勿重複 |
繪圖優化:InvalidateRect + GetClipBox
InvalidateRect(&rect, TRUE):標記無效區,觸發 WM_PAINT;
OnDraw 中呼叫 pDC->GetClipBox(&rect) 取得實際需重繪區域,僅繪製該區內物件;
- 視窗縮放、遮蔽恢復同樣觸發
OnDraw。
幾何測試 API
PtInRect(&rect, point):點在矩形內;
PtInRegion(rgn, point):點在區域 (橢圓/多邊形) 內;
GetClientRect(&rect):取得客戶區座標;
SelectStockObject(GRAY_BRUSH):選入預設筆/刷/字型,返回舊物件指標。
成員初始化列表寫法
CMyView::CMyView()
: m_rectEllipse(0, 0, 200, 200) // CRect 成員直接構造
, m_nColor(GRAY_BRUSH) {}
MFC 訊息映射 vs SDK 視窗程序
| SDK | MFC |
註冊 WNDCLASS + lpfnWndProc | 統一視窗類 + 統一視窗程序 |
CreateWindow 指定類名 | 句柄映射表查找 CWnd* |
DispatchMessage → 視窗程序 switch(msg) | 運行時類系統 → 靜態訊息映射表 → 呼叫成員函數 |
映射模式
- MM_TEXT:裝置座標 (像素),X 右增、Y 下增;
- 固定比例模式:邏輯單位對應實體尺寸,X 右增、Y **上增** (笛卡兒座標);
MM_HIENGLISH (0.001 in)、MM_HIMETRIC (0.01 mm)、MM_LOENGLISH (0.01 in)、MM_LOMETRIC (0.1 mm)、MM_TWIPS (1/1440 in);
- 座標轉換:
SetViewportOrg/SetWindowOrg 移動原點;
DPtoLP/LPtoDP 裝置↔邏輯座標互轉。