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

Win32 組語教學:選單資源的建立與訊息處理

     編輯:組合語言

選單在 Windows 程式中的地位

選單是使用者探索程式功能的主要入口。良好的選單設計遵循慣例:檔案、編輯 開頭,說明 結尾;啟動對話方塊的項目以省略號(...)結尾。選單屬於資源,編譯連結後嵌入可執行檔,執行期由系統載入。本課詳細說明選單資源腳本語法、兩種掛載方式,以及 WM_COMMAND 訊息處理。

資源腳本語法詳解

基本結構

MyMenu MENU
BEGIN
    POPUP "&PopUp"
    BEGIN
        MENUITEM "&Say Hello", IDM_HELLO
        MENUITEM "Say &GoodBye", IDM_GOODBYE
        MENUITEM SEPARATOR
        MENUITEM "E&xit", IDM_EXIT
    END
    MENUITEM "&Test", IDM_TEST
END
  • MENU 關鍵字宣告選單資源,MyMenu 為資源名稱。
  • POPUP 定義可展開的子選單,MENUITEM 定義葉節點項目。
  • & 標記熱鍵字元(底線),如 "&PopUp" 顯示為 PopUp,按 Alt+P 開啟。
  • SEPARATOR 產生分隔線。
  • 選項屬性:GRAYED(灰色停用)、INACTIVE(正常色停用)、MENUBREAK(換欄)、HELP(右對齊)。

兩種掛載選單的方式

方式一:在視窗類別中指定(預設選單)

.DATA
MenuName db "FirstMenu",0
...
mov wc.lpszMenuName, OFFSET MenuName

所有由此類別建立的視窗共用同一選單。簡單直觀,適合單一視窗應用。

方式二:在 CreateWindowEx 中指定(覆蓋類別選單)

.DATA?
hMenu HMENU ?
...
invoke LoadMenu, hInst, OFFSET MenuName
mov hMenu, eax
invoke CreateWindowEx, NULL, ADDR ClassName, ADDR AppName, \
    WS_OVERLAPPEDWINDOW, ..., NULL, hMenu, hInst, NULL

呼叫 LoadMenu 取得選單句柄,傳給 CreateWindowEx 的 hMenu 參數。此法允許同一類別建立不同選單的視窗,彈性較高。

WM_COMMAND 訊息處理

使用者選取選單項目時,視窗程序收到 WM_COMMAND,wParam 低位字為選單項目 ID,高位字為 0,lParam 為 0。範例處理邏輯:

.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF ax==IDM_TEST
    invoke MessageBox,NULL,ADDR Test_string,OFFSET AppName,MB_OK
.ELSEIF ax==IDM_HELLO
    invoke MessageBox, NULL,ADDR Hello_string, OFFSET AppName,MB_OK
.ELSEIF ax==IDM_GOODBYE
    invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName, MB_OK
.ELSE
    invoke DestroyWindow,hWnd
.ENDIF

完整範例程式碼

組語主程式 (menu.asm)

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
MenuName db "FirstMenu",0
Test_string db "You selected Test menu item",0
Hello_string db "Hello, my friend",0
Goodbye_string db "See you again, bye",0

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.const
IDM_TEST equ 1
IDM_HELLO equ 2
IDM_GOODBYE equ 3
IDM_EXIT equ 4

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF ax==IDM_TEST
invoke MessageBox,NULL,ADDR Test_string,OFFSET AppName,MB_OK
.ELSEIF ax==IDM_HELLO
invoke MessageBox, NULL,ADDR Hello_string, OFFSET AppName,MB_OK
.ELSEIF ax==IDM_GOODBYE
invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName, MB_OK
.ELSE
invoke DestroyWindow,hWnd
.ENDIF
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

資源腳本 (menu.rc)

#define IDM_TEST 1
#define IDM_HELLO 2
#define IDM_GOODBYE 3
#define IDM_EXIT 4
FirstMenu MENU
{
POPUP "&PopUp"
{
MENUITEM "&Say Hello",IDM_HELLO
MENUITEM "Say &GoodBye", IDM_GOODBYE
MENUITEM SEPARATOR
MENUITEM "E&xit",IDM_EXIT
}
MENUITEM "&Test", IDM_TEST
}

進階議題:動態選單操作

除靜態資源外,執行期可呼叫 GetMenu、GetSubMenu、AppendMenu、InsertMenu、DeleteMenu、EnableMenuItem、CheckMenuItem 等 API 動態增刪修改選單項目,實現內容相關選單。這部分將在後續進階教學中探討。

總結

選單資源定義簡單、載入高效,搭配 WM_COMMAND 即可實現完整命令路由。掌握兩種掛載方式與資源腳本語法,是 Win32 組語 GUI 開發的基本功。

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