Windows 程式設計/對話方塊
人們熟悉對話方塊。它們是 Windows 系統上彈出顯示訊息並允許使用者設定引數的灰色視窗。對話方塊有三種類型:無模式、模態和系統模態。
- 模態
- 模態對話方塊通常用於程式內部,用於顯示訊息和設定程式引數。模態對話方塊會出現在螢幕最前面,在模態對話方塊開啟時,您無法使用程式。要繼續使用程式,必須關閉模態對話方塊。
- 系統模態
- 系統模態對話方塊與模態對話方塊類似,但它們會覆蓋整個桌面區域。當系統模態對話方塊開啟時,螢幕上其他任何內容都無法單擊或選擇。
- 無模式
- 無模式對話方塊可以取消選擇,並且可以將控制權從無模式對話方塊轉移到其他視窗。無模式對話方塊通常用作建立視窗的快速簡便方法,無需註冊視窗類。無模式對話方塊在 Windows 控制面板中很常見。
MessageBox
[edit | edit source]最簡單的對話方塊型別是 MessageBox 函式。MessageBox 函式接受 5 個引數:父視窗控制代碼、訊息、標題和選項。如果父視窗控制代碼為 NULL,則訊息框為無模式的。如果您為父視窗提供控制代碼,則 MessageBox 可以變為父視窗的模態視窗。
MessageBox 對話方塊有多種不同的選項可以指定:按鈕型別、圖示、模態(模態/無模式)和文字對齊方式。這些選項被指定為位標誌,可以使用按位 OR 運算子將它們組合在一起。
按鈕
[edit | edit source]訊息框可以具有標準的“確定”或“取消”按鈕,也可以具有“是、否、取消”配置或許多衍生配置。每個訊息框只能使用一種主要按鈕方案
- MB_ABORTRETRYIGNORE: 訊息框包含三個按鈕:中止、重試和忽略。
- MB_CANCELTRYCONTINUE: 與 MB_ABORTRETRYIGNORE 相同,但在 Windows 2000/XP 上更常用。
- MB_OK: 訊息框包含一個“確定”按鈕。這是預設值。
- MB_OKCANCEL: 訊息框包含兩個按鈕:“確定”和“取消”。
- MB_RETRYCANCEL: 訊息框包含兩個按鈕:“重試”和“取消”。
- MB_YESNO: 訊息框包含兩個按鈕:“是”和“否”。
- MB_YESNOCANCEL: 訊息框包含三個按鈕:“是”、“否”和“取消”。
要在訊息框中顯示圖示,請指定以下值之一。此外,訊息框可以透過指定“MB_HELP”標誌新增額外的“幫助”按鈕。“預設按鈕”是一個概念,我們將在本章中經常看到,它是對話方塊開啟時自動選擇的按鈕。Windows 提供了使用 MB_DEFBUTTONx 宏將預設按鈕設定為訊息框上的任何按鈕的能力。以下是一個示例
MessageBox(NULL, "This is a Test", "Test", MB_OKCANCEL|MB_HELP|MB_DEFBUTTON2);
這將有一個帶有“確定”、“取消”和“幫助”按鈕的訊息框,並且“取消”按鈕將自動被選中。
圖示
[edit | edit source]訊息框可能沒有圖示,也可能只有一個圖示。您不應指定訊息框具有多個圖示。根據 MSDN,不同的圖示是
- MB_ICONEXCLAMATION: 訊息框中會出現一個感嘆號圖示。
- MB_ICONWARNING: 訊息框中會出現一個感嘆號圖示。
- MB_ICONINFORMATION: 訊息框中會出現一個包含小寫字母 i 的圓圈圖示。
- MB_ICONASTERISK: 訊息框中會出現一個包含小寫字母 i 的圓圈圖示。
- MB_ICONQUESTION: 訊息框中會出現一個問號圖示。
問號訊息圖示不再推薦使用,因為它不能清楚地表示特定型別的訊息,並且將訊息作為問題來措辭可能適用於任何型別的訊息。此外,使用者可能會將訊息符號問號與幫助資訊混淆。因此,不要在您的訊息框中使用此問號訊息符號。系統繼續支援其包含只是為了向後相容。 - MB_ICONSTOP: 訊息框中會出現一個停止標誌圖示。
- MB_ICONERROR: 訊息框中會出現一個停止標誌圖示。
- MB_ICONHAND: 訊息框中會出現一個停止標誌圖示。
模態
[edit | edit source]最後,MessageBox 可以透過使用另一個識別符號定義為模態、無模式或系統模態:MB_APPLMODAL、MB_SYSTEMMODAL 或 MB_TASKMODAL。MB_APPLMODAL 是預設值,並且只有在為函式指定了父視窗控制代碼時才有效。還有許多其他選項可用,請檢視 MSDN 瞭解詳細資訊。
對話方塊過程
[edit | edit source]對話方塊過程與視窗過程略有不同。具體來說,它們返回 BOOL 值,而不是 LRESULT 值。此外,對話方塊沒有預設的訊息處理函式,因為訊息並不總是需要處理。具體來說,Windows 管理對話方塊,Windows 將處理未使用的訊息。如果對話方塊處理了某個訊息,它應該返回 TRUE。如果訊息未處理,該函式應該返回 FALSE。此外,對話方塊不會收到 WM_CREATE 訊息,而是收到 WM_INITDIALOG 訊息。此外,當對話方塊完成其工作時,它應該呼叫 EndDialog 函式。
以下是一個對話方塊函式的骨架示例
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_DESTROY:
EndDialog(hDlg, 0);
return TRUE;
}
return FALSE;
}
建立模態對話方塊
[edit | edit source]定義對話方塊過程後,可以透過呼叫 DialogBox 或 DialogBoxParam 函式建立對話方塊。這些函式返回一個 NRESULT 值,該值是傳遞給對話方塊過程中 EndDialog 函式的整數。
DialogBox 函式在對話方塊關閉之前不會返回。這意味著,從本質上講,程式會凍結,直到我們關閉對話方塊。DialogBox 函式需要 2 個控制代碼:模組例項控制代碼和父視窗控制代碼。此外,DialogBox 函式要求傳遞一個字串來命名定義對話方塊的資源。DialogBox 的最後一個引數是指向您已經定義的對話方塊過程函式的指標。
要將引數傳遞給對話方塊,可以使用 DialogBoxParam 函式。DialogBoxParam 具有與常規版本相同的引數,除了它接受第五個引數作為 32 位指標。這個 32 位值將作為 WM_INITDIALOG 訊息的 LPARAM 元素傳遞。
DialogBox 和 DialogBoxParam 都要求對話方塊在資源中定義。但是,如果您想在執行時建立對話方塊,您可以使用 **DialogBoxIndirect** 或 **DialogBoxIndirectParam** 函式。在間接定義對話方塊時,我們需要填充 DLGTEMPLATE 結構,並將指向該結構的指標傳遞給函式,以代替資源識別符號。DLGTEMPLATE 包含用於確定對話方塊某些特徵的欄位,例如尺寸和螢幕位置。
DLGITEMTEMPLATE 結構用於定義單個對話方塊項。有關此主題的更多資訊,請搜尋 MSDN。
無模式對話方塊是不同型別的東西,更像視窗而不是對話方塊。首先,我們需要修改訊息迴圈,以確保對話方塊訊息被正確路由。
while(GetMessage(&msg, NULL, 0, 0))
{
if(!IsDialogMessage(hDlg, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
現在,我們有兩種方法可以在資源指令碼中定義訊息框,有類或無類。我們將依次討論每種方法。
我們可以在資源指令碼中使用 DIALOG 關鍵字定義對話方塊。資源將有一個與其關聯的 ID(數字或字串),並且此 ID 可以直接傳遞給 CreateDialog 函式。
如果我們想在視窗類的基礎上定義一個無模式對話方塊,我們可以使用一些額外的功能來簡化工作。首先,我們建立一個 WNDCLASS 結構,其中包含有關對話方塊的資訊。但是,有一點不同,我們必須將 cbWndExtra 欄位設定為 DLGWINDOWEXTRA 值。
wnd.cbWndExtra = DLGWINDOWEXTRA;
然後,我們像往常一樣註冊類。由於我們像註冊普通視窗一樣註冊視窗類,因此無模式對話方塊使用常規視窗過程,而不是對話方塊過程,這一點並不奇怪。現在,Windows 按名稱識別類,因此我們應該記住類的名稱。假設我們給我們的類命名為“MyDlgClass”。我們可以像這樣建立一個對話方塊資源
MYDLGCLASS DIALOG DISCARDABLE 100, 100, 200, 200 CAPTION "My Dialog Box" CLASS "MyDlgClass" FONT 8, "MS Sans Serif" BEGIN ... END
請注意名為“CLASS”的欄位?這與我們在 WNDCLASS 結構中用於命名類的字串相同。重要的是這兩個字串必須相同,因為 Windows 需要此字串將 WNDCLASS 和對話方塊資源連結起來。還要注意,我們使用字串“MYDLGCLASS”來標識對話方塊資源。這不是強制性的,但它確實在以後使事情變得更方便。
現在,我們將呼叫更易於使用的函式 **CreateDialog**,而不是呼叫 CreateWindow。我們不使用 DialogBox 函式,因為 CreateDialog 會立即返回,並且不會停止程式執行。
這是一個例子
HWND hDlg; hDlg = CreateDialog(hInst, "MyDlgClass", hwndParent, MyDlgProc);
在這裡,我們說“hInst”是應用程式的例項控制代碼,而“hwndParent”是對話方塊父視窗的控制代碼。如果 hwndParent 引數為 NULL,則對話方塊將沒有父視窗。當無模式對話方塊完成時,它會呼叫“DestroyWindow”,而不是像模態對話方塊那樣呼叫“EndDialog”。
**通用對話方塊** 是一個函式庫,它可以自動生成 Windows 中一些最常見的對話方塊。這是一種努力,旨在使不同程式之間具有一定程度的連續性,這樣,每個不同的程式就不會建立自己的專有“開啟檔案”對話方塊,例如。
每個通用對話方塊通常都有一個函式,該函式接受指向結構的指標。此結構專門針對每個不同的控制元件進行定義。可以透過包含 <commdlg.h> 標頭檔案並將連結到 **comdlg32.dll** 庫來將通用控制元件新增到專案中。
透過此庫提供的一些通用控制元件包括“選擇字型”對話方塊、“開啟檔案”和“儲存檔案”框以及“顏色調色盤”對話方塊。
**ChooseColor** 函式會調出顏色調色盤視窗,並向您的程式返回一個 32 位顏色值。
BOOL ChooseColor(LPCHOOSECOLOR lpcc);
ChooseColor 接受一個引數,它以指向 CHOOSECOLOR 結構的指標的形式出現。此結構用各種值初始化,當函式返回時,CHOOSECOLOR 結構將包含顏色值程式碼。
這兩個函式會調出在幾乎所有 Windows 應用程式中都熟悉的開啟檔案和儲存檔案對話方塊。
BOOL GetOpenFileName(LPOPENFILENAME lpofn); BOOL GetSaveFileName(LPOPENFILENAME lpofn);
這兩個函式都接受指向 OPENFILENAME 結構的指標。此結構控制諸如可以載入的副檔名以及要查詢的起始路徑等內容。當函式返回時,該結構將包含所選檔案的名稱。一旦您的程式獲得了此資訊,您就可以使用檔案 I/O API 來訪問該檔案。
ChooseFont 函式會調出一個熟悉的對話方塊,允許使用者選擇字型和各種字型屬性,例如大小、下劃線/粗體/斜體、顏色等。此函式接受指向 CHOOSEFONT 結構的指標。
BOOL ChooseFont(LPCHOOSEFONT lpcf);
對話方塊可以在資源指令碼中指定,以處理建立對話方塊可能包含的所有不同子視窗(按鈕和編輯框等)的繁瑣任務。此過程在附錄中的資源指令碼參考中詳細描述。在這裡,我們將討論使用資源指令碼定義對話方塊的一些基礎知識。
對話方塊資源使用 **DIALOG**(必須全部大寫)關鍵字指定。DIALOG 關鍵字在資源識別符號之前,後面跟著一系列尺寸值。
ID_DLGBOX DIALOG X, Y, CX, CY
X 和 Y 是對話方塊左上角相對於螢幕左上角的位置座標。請記住,所有座標都從左上角的 (0,0) 開始。下一組數字 CX 和 CY 是對話方塊的尺寸。這些尺寸不包括標題欄(如果有),因此將您的 Y 值設定為 0 將建立一個只有標題欄的對話方塊。
+---------------> X
["DialogBox" [_][O][x]]
+ | |
| | |
| | |
| | |
| | |
| | |
v | |
Y | |
| |
| |
| |
+-----------------------+
在 DIALOG 宣告之後,可以填寫許多其他欄位,以提供有關對話方塊的資訊
ID_DLGBOX DIALOG 100, 100, 200, 150 STYLE WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE CAPTION "Title Bar Text" FONT 8, "MS Sans Serif"
STYLE 宣告包含您將在 WNDCLASS 結構中或 CreateWindow 函式的 style 欄位中使用的所有視窗樣式,它們以按位或運算子連線。所有相同的值都可用。CAPTION 是對話方塊的標題。FONT 是在對話方塊的所有表面上使用的磅值和 TrueType 字型。可以指定任何字型和大小,但如果字型太大,您的對話方塊會非常煩人。
現在,一旦我們按我們想要的方式調整了對話方塊的大小和形狀,我們就可以開始用控制按鈕、編輯框以及各種其他好東西來填充它。首先,我們使用 BEGIN 和 END 標記
ID_DLGBOX DIALOG 100, 100, 200, 150 STYLE WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE CAPTION "Title Bar Text" FONT 8, "MS Sans Serif" BEGIN ... END
接下來,我們可以開始使用以下格式用按鈕、複選框或任何我們想要的東西填充對話方塊
ID_DLGBOX DIALOG 100, 100, 200, 150 STYLE WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE CAPTION "Title Bar Text" FONT 8, "MS Sans Serif" BEGIN PUSHBUTTON "OK", IDOK, 10, 10, 50, 15, WS_TABSTOP CHECKBOX "Box 1", IDC_CB1, 10, 30, 50, 15, WS_TABSTOP EDITTEXT IDC_EDIT1, 10, 50, 100, 100 END
在宣告之後,您可以選擇包括一個或多個樣式標誌,以指定您希望特定控制元件的外觀。WS_TABSTOP 識別符號指定當您在鍵盤上按 TAB 鍵時,哪些控制元件可以被選中。當您按 TAB 鍵時,控制元件會在對話方塊控制元件之間切換,順序與它們在資源指令碼中指定的順序相同(從上到下)。