首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC 動態對話框模板實作:無資源檔建立對話框的完整指南

     編輯:關於VC++

為什麼需要動態對話框模板?

  • 靜態資源 (.rc) 編譯進 EXE,難以執行期依條件產生不同介面
  • 外掛/擴充架構需獨立打包對話框定義,避免資源 ID 衝突
  • 嵌入式/精簡部署需減少資源段大小

核心 API:DialogBoxIndirect / CreateDialogIndirect (Win32) → MFC 封裝 CDialog::InitModalIndirect / CDialog::CreateIndirect。

對話框模板記憶體布局

變長結構,依序包含:

  1. DLGTEMPLATE (固定頭) + 變長欄位:選單、類別名、標題、字型 (若有 DS_SETFONT)
  2. 對齊到 DWORD 邊界
  3. DLGITEMTEMPLATE 陣列 (每個控制項) + 各自變長欄位:類別名、標題、建立資料

陷阱:座標/尺寸單位為 **對話框單位 (DLU)**,非像素。1 水平 DLU = 1/4 平均字寬,1 垂直 DLU = 1/8 平均字高。需用 MapDialogRect (執行期) 或手動換算:


CSize base = GetDialogBaseUnits();
xDLU = MulDiv(xPix, 4, base.cx);
yDLU = MulDiv(yPix, 8, base.cy);

輔助建構類 CDlgTemplateBuilder

封裝記憶體配置、對齊、字串轉 Unicode、cdit 計數自動遞增:


// 使用範例
CDlgTemplateBuilder dtb;
DLGTEMPLATE* pTempl = dtb.Begin(WS_POPUP|DS_MODALFRAME, 100, 100, 300, 200, L"標題");
dtb.AddItem(WS_CHILD|WS_VISIBLE|WS_TABSTOP, 10, 10, 100, 14, 0xFFFF, 0x0081, L"確定", IDC_OK); // 按鈕
dtb.AddItem(WS_CHILD|WS_VISIBLE|WS_BORDER, 10, 30, 200, 14, 0xFFFF, 0x0081, L"", IDC_EDIT); // 編輯框
dtb.AddItem(WS_CHILD|WS_VISIBLE, 10, 50, 200, 100, 0xFFFF, 0x0082, L"提示文字", IDC_STATIC); // 靜態文字
dlg.InitModalIndirect(pTempl, this);
dlg.DoModal();

AddItem 參數:樣式、x、y、cx、cy、擴充樣式、類別原子碼 (0xFFFF+系統類別)、標題、ID。

系統控制項原子碼速查 (0xFFFF + 以下值)

值控制項類別名
0x0080ButtonBUTTON
0x0081EditEDIT
0x0082StaticSTATIC
0x0083ListBoxLISTBOX
0x0084ScrollBarSCROLLBAR
0x0085ComboBoxCOMBOBOX

字型處理策略

  • 模板指定 DS_SETFONT + 字型大小/名稱 → 較複雜
  • 推薦:模板不指定字型 → OnInitDialog 呼叫 SetFont 套用預設 GUI 字型,簡單且自動適應系統 DPI

系統圖示資源 ID 技巧

模板中靜態圖示控制項若用系統圖示 (IDI_QUESTION 等),ID 值 ≥ 32512 (IDI_APPLICATION) 會被視為系統圖示。做法:

  1. 模板寫入 0xFFFF + 0 (佔位 ID=0)
  2. OnInitDialog 呼叫 LoadIcon(NULL, IDI_QUESTION) 取得 HICON
  3. ((CStatic*)GetDlgItem(IDC_ICON))->SetIcon(hIcon) 實際設定

完整可執行範例:CStringDialog

輸入提示字串與標題,動態建立含「圖示 + 提示文字 + 編輯框 + 確定/取消」的對話框,返回使用者輸入字串。原始碼展示 CDlgTemplateBuilder 所有細節。

ATL 正則表達式替代方案 (附錄)

發現 atlrx.h 提供 CAtlRegExp/CAtlREMatchContext,無需 .NET 依賴。語法差異:分組用 {...} 而非 (...);空白用 \b 而非 \s。封裝為 CRegex 提供 NextMatch()/GetMatch()/Replace()/Split() 介面,使用體驗接近 .NET Regex。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved