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

Win32 組語教學:對話方塊為主視窗的應用程式設計

     編輯:組合語言

為何選擇對話方塊作為主視窗?

在前一課的子視窗控件範例中,您可能發現兩個困擾:無法用 Tab 鍵在控件間切換焦點,且背景色需手動協調。根本原因在於——子視窗控件原本就是為對話方塊設計的。對話方塊內建管理程序,自動處理鍵盤導航(Tab/Enter/Esc)、控件焦點切換、預設按鈕觸發等瑣事,讓開發者專注於商業邏輯。本課將示範兩種以對話方塊為主視窗的經典架構。

核心概念:模態與非模態

  • 模態對話方塊:呼叫 DialogBoxParam,進入專屬訊息迴圈,阻擋同應用程式其他視窗互動,直到 EndDialog 結束。適用於設定視窗、關鍵確認。
  • 非模態對話方塊:呼叫 CreateDialogParam,共用主訊息迴圈,需在迴圈中呼叫 IsDialogMessage 轉發鍵盤訊息。適用於尋找/取代、工具面板。

方法一:將對話方塊模板註冊為視窗類別

在資源腳本(.rc)中定義對話方塊時,加入 CLASS "DLGCLASS" 陳述式;組語中註冊 WNDCLASSEX 時,將 cbWndExtra 設為 DLGWINDOWEXTRA,lpszClassName 對應 DLGCLASS。隨後呼叫 CreateDialogParam 建立非模態對話方塊,系統依模板自動建立所有子控件。主訊息迴圈需加入 IsDialogMessage 以啟用鍵盤導航。

資源腳本關鍵片段 (dialog.rc)

MyDialog DIALOG 10, 10, 205, 60
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "Our First Dialog Box"
CLASS "DLGCLASS"
BEGIN
    EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
    DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
    PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13, WS_GROUP
END

組語關鍵片段 (dialog.asm - 方法一)

mov wc.cbWndExtra,DLGWINDOWEXTRA
mov wc.lpszClassName,OFFSET ClassName
...
invoke CreateDialogParam,hInstance,ADDR DlgName,NULL,NULL,NULL
mov hDlg,eax
...
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke IsDialogMessage, hDlg, ADDR msg
.IF eax == FALSE
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
.ENDW

方法二:直接呼叫 DialogBoxParam 建立模態對話方塊

此法完全不需註冊視窗類別、不需主訊息迴圈。DialogBoxParam 內部執行專屬模態迴圈,直接將訊息分派給 DlgProc。對話方塊程序回傳 TRUE(已處理)或 FALSE(交由預設處理),不呼叫 DefWindowProc。關閉時呼叫 EndDialog 而非 DestroyWindow。

資源腳本差異 (dialog.rc - 方法二)

MyDialog DIALOG 10, 10, 205, 60
STYLE ... (同方法一)
CAPTION "Our Second Dialog Box"
MENU IDR_MENU1          ; 以整數 ID 指定選單
BEGIN
    EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
    DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
    PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
END
IDR_MENU1 MENU
BEGIN
    POPUP "Test Controls"
    BEGIN
        MENUITEM "Get Text", IDM_GETTEXT
        MENUITEM "Clear Text", IDM_CLEAR
        MENUITEM "", , 0x0800
        MENUITEM "E&xit", IDM_EXIT
    END
END

組語完整流程 (dialog.asm - 方法二)

start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName, NULL, addr DlgProc, NULL
invoke ExitProcess,eax

DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
    invoke GetDlgItem, hWnd, IDC_EDIT
    invoke SetFocus, eax
    mov eax, TRUE
    ret
.ELSEIF uMsg==WM_CLOSE
    invoke SendMessage, hWnd, WM_COMMAND, IDM_EXIT, 0
.ELSEIF uMsg==WM_COMMAND
    mov eax, wParam
    .IF lParam==0
        .IF ax==IDM_GETTEXT
            invoke GetDlgItemText, hWnd, IDC_EDIT, ADDR buffer, 512
            invoke MessageBox, NULL, ADDR buffer, ADDR AppName, MB_OK
        .ELSEIF ax==IDM_CLEAR
            invoke SetDlgItemText, hWnd, IDC_EDIT, NULL
        .ELSEIF ax==IDM_EXIT
            invoke EndDialog, hWnd, NULL
        .ENDIF
    .ELSE
        mov edx, wParam
        shr edx, 16
        .IF dx==BN_CLICKED
            .IF ax==IDC_BUTTON
                invoke SetDlgItemText, hWnd, IDC_EDIT, ADDR TestString
            .ELSEIF ax==IDC_EXIT
                invoke SendMessage, hWnd, WM_COMMAND, IDM_EXIT, 0
            .ENDIF
        .ENDIF
    .ENDIF
.ELSE
    mov eax, FALSE
    ret
.ENDIF
mov eax, TRUE
ret
DlgProc endp

關鍵 API 對照表

傳統視窗 API對話方塊專用 API說明
GetWindowTextGetDlgItemText以控件 ID 而非句柄取得文字
SetWindowTextSetDlgItemText以控件 ID 設定文字
SendMessage(hCtrl, ...)SendDlgItemMessage(hDlg, id, ...)簡化控件通訊
CreateWindowEx(資源模板自動建立)無需手動建立子控件

實戰提醒

  • WM_INITDIALOG 是對話方塊建立後、顯示前的初始化時機,必須回傳 TRUE(除非自行設定焦點)。
  • 模態對話方塊不會收到 WM_DESTROY,關閉處理請放在 WM_CLOSE 或命令項目中呼叫 EndDialog。
  • 模態對話方塊若需掛載選單,資源腳本必須使用 MENU IDR_MENU1 整數 ID 形式,不可用字串名稱。
  • 若需圖示,可在 WM_INITDIALOG 中發送 WM_SETICON 訊息自行設定。

總結

對話方塊將視窗建立、控件佈局、鍵盤導航封裝為「黑盒子」,極大降低組語開發 Windows GUI 的複雜度。方法一適合需自訂視窗類別行為(如自訂圖示、游標、背景筆刷)的場合;方法二則是快速開發工具型對話方塊的最佳選擇。掌握兩種架構,即可靈活應對各類 GUI 專案需求。

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