對話框不僅是獨立視窗,也可作為主視窗的輸入裝置(模態/非模態),並可整合系統預建的通用對話框(開啟檔案、儲存、列印、色彩、字型、搜尋),提供一致使用者體驗。本文說明 DialogBoxParam/CreateDialogParam 兩種建立模式、IsDialogMessage 鍵盤導航、通用對話框架構與 OPENFILENAME 結構詳細用法,附 MASM 範例。
| 模式 | 建立函式 | 訊息迴圈 | 適用場景 |
|---|---|---|---|
| 模態 | DialogBoxParam | 系統內建,阻塞呼叫執行緒 | 需使用者立即回應的設定、確認 |
| 非模態 | CreateDialogParam | 主迴圈需呼叫 IsDialogMessage | 工具列、屬性面板、尋找取代視窗 |
非模態對話框主迴圈範例:
.WHILE TRUE
invoke GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (!eax)
.if !IsDialogMessage(hModelessDlg, ADDR msg)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.endif
.ENDW
IsDialogMessage 處理 Tab/Shift+Tab 焦點切換、Enter 啟動預設按鈕、Esc 關閉等鍵盤邏輯。
位於 comdlg32.dll,連結需 comdlg32.lib。常用函式:
GetOpenFileName:開啟檔案GetSaveFileName:另存新檔ChooseColor:色彩選擇ChooseFont:字型選擇PrintDlg:列印設定FindText / ReplaceText:尋找/取代所有函式接收單一參數:指向對應結構體的指標(如 OPENFILENAME、CHOOSECOLOR 等)。
OPENFILENAME STRUCT
lStructSize DWORD ? ; 結構大小,必填
hwndOwner HWND ? ; 擁有者視窗
hInstance HINSTANCE ? ; 實例控制碼(自訂範本時用)
lpstrFilter LPCSTR ? ; 過濾器字串雙重空字元結尾
lpstrCustomFilter LPSTR ? ; 使用者自訂過濾器緩衝區
nMaxCustFilter DWORD ? ; 自訂過濾器緩衝區大小
nFilterIndex DWORD ? ; 預設過濾器索引(1-based)
lpstrFile LPSTR ? ; 檔名緩衝區(輸入/輸出),最大 260 字元
nMaxFile DWORD ? ; 緩衝區大小
lpstrFileTitle LPSTR ? ; 僅檔名部分緩衝區(輸出)
nMaxFileTitle DWORD ? ; 檔名緩衝區大小
lpstrInitialDir LPCSTR ? ; 初始目錄
lpstrTitle LPCSTR ? ; 對話框標題
Flags DWORD ? ; 風格旗標組合
nFileOffset WORD ? ; 完整路徑中檔名起始位移(輸出)
nFileExtension WORD ? ; 副檔名起始位移(輸出)
lpstrDefExt LPCSTR ? ; 預設副檔名
lCustData LPARAM ? ; 自訂資料傳遞給 Hook
lpfnHook DWORD ? ; Hook 程式指標
lpTemplateName LPCSTR ? ; 自訂範本資源名
OPENFILENAME ENDS
OFN_FILEMUSTEXIST:檔名必須存在OFN_PATHMUSTEXIST:路徑必須存在OFN_LONGNAMES:支援長檔名OFN_EXPLORER:使用資源管理員風格外觀OFN_HIDEREADONLY:隱藏唯讀核取方塊OFN_OVERWRITEPROMPT:儲存時檔案存在提示覆寫(GetSaveFileName 專用)OFN_NOCHANGEDIR:不改變目前工作目錄選單「File→Open」呼叫 GetOpenFileName,使用者選擇檔案後,彈出訊息框顯示完整路徑、純檔名、副檔名。
.if ax==IDM_OPEN
mov ofn.lStructSize, SIZEOF ofn
push hWnd; pop ofn.hwndOwner
push hInstance; pop ofn.hInstance
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile, MAXSIZE
mov ofn.Flags, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_LONGNAMES|OFN_EXPLORER|OFN_HIDEREADONLY
mov ofn.lpstrTitle, OFFSET OurTitle
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
; 組裝輸出字串...
.endif
FilterString db "All Files",0,"*.*",0
db "Text Files",0,"*.txt",0,0
格式:描述\0模式\0描述\0模式\0\0。系統僅使用模式部分比對,描述顯示於下拉選單。
; 完整路徑在 ofn.lpstrFile (buffer)
; 檔名起始位移 in ofn.nFileOffset (WORD)
; 副檔名起始位移 in ofn.nFileExtension (WORD)
mov eax, ofn.lpstrFile
push ebx
xor ebx, ebx
mov bx, ofn.nFileOffset
add eax, ebx ; eax 指向純檔名
pop ebx
invoke lstrcat, OFFSET OutputString, eax
mov eax, ofn.lpstrFile
push ebx
xor ebx, ebx
mov bx, ofn.nFileExtension
add eax, ebx ; eax 指向副檔名
pop ebx
invoke lstrcat, OFFSET OutputString, eax
因 nFileOffset/Extension 為 WORD,需擴展至 32 位元後加至基址。
invoke RtlZeroMemory, OFFSET OutputString, OUTPUTSIZE
下次使用前必須歸零,否免殘留字串干擾。
設定 Flags |= OFN_ENABLEHOOK,lpfnHook 指向回呼函式 UINT_PTR CALLBACK OFNHookProc(HWND, UINT, WPARAM, LPARAM)。可攔截訊息、自訂控件、驗證輸入。Hook 返回 TRUE 表已處理,FALSE 表交由預設處理。
對話框是 Windows 介面開發的核心元件。掌握模態/非模態建立差異、IsDialogMessage 鍵盤導航、通用對話框統一介面與 OPENFILENAME 靈活配置,並善用 nFileOffset/Extension 擷取路徑組件,即可開發出符合平台規範、使用者體驗一致的專業應用程式。