.asm文件如下:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
IDM_MAIN equ 2000h
IDM_SUBMENU1 equ 4101h
IDM_SUBMENU2 equ 4102h
IDM_EXIT equ 4103h
IDA_ACCELERATOR equ 3004h
.data
ClassName db "Menuandacccelerator",0
AppName db "使用菜单和加速例子程序",0
szAcce db "这个消息由加速键产生",0
szMenu db "这个消息由菜单产生",0
szSM1 db "子菜单1",0
szSM11 db "子菜单111",0
szSM2 db "子菜单2",0
;MenuName db "MyMenu",0 ;方法一 无需此步。方法二 第二步:数据段中声明资源文件中表示菜单的字符串
.data?
hInstance HINSTANCE ?
hMenu dd ?
hSubMenu dd ?
hAccelerator dd ?
.code
WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
;wParam参数高16位是通知码,低16位是命令ID lParam是发送WM_COMMAND消息的子窗口句柄
;菜单消息的通知码是0,加速键消息的通知码是1
;对于菜单和加速键引发的WM_COMMAND消息,lParam的值为0
LOCAL stPos:POINT
.if uMsg==WM_CREATE
invoke GetSubMenu,hMenu,0
mov hSubMenu,eax
.elseif uMsg==WM_RBUTTONDOWN ;获取右键在窗口中点下的坐标
invoke GetCursorPos,addr stPos
invoke TrackPopupMenu,hSubMenu,TPM_LEFTALIGN,stPos.x,stPos.y,NULL,hWnd,NULL
.elseif uMsg==WM_COMMAND
mov eax,wParam
mov ebx,eax
rol ebx,16
.if ax==IDM_SUBMENU1
.if bx ;如果是加速键
invoke MessageBox,NULL,addr szSM11,addr szAcce,MB_OK
.else ;如果是菜单键
invoke MessageBox,NULL,addr szSM1,addr szAcce,MB_OK
.endif
.elseif ax==IDM_SUBMENU2
.if bx
invoke MessageBox,NULL,addr szSM2,addr szAcce,MB_OK
.else
invoke MessageBox,NULL,addr szSM2,addr szAcce,MB_OK
.endif
.elseif ax==IDM_EXIT
invoke DestroyWindow,hWnd
.endif
.elseif uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX ;wc是一个窗口类的结构体变量
LOCAL msg: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 ;指定在WNDCLASSEX结构体后面申请多少个字节的空间
mov wc.cbWndExtra,NULL ;指定在窗口实例后面申请空间的字节数
push hInst
pop wc.hInstance ;保存窗口实例句柄
mov wc.hbrBackground,COLOR_WINDOW+1 ;指定窗口背景颜色
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 ;指定在该窗口上显示的光标样式
;mov wc.lpszMenuName,OFFSET MenuName ; 方法一:无需此步 方法二 第三步:(菜单名为字符串时使用此方法)
invoke RegisterClassEx,addr wc
;——————————————————————
;创建窗口对象
;——————————————————————
invoke CreateWindowEx,NULL,\
ADDR ClassName,\
ADDR AppName,\
WS_OVERLAPPEDWINDOW,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
CW_USEDEFAULT,\
NULL,\
hMenu,\ ;NULL,\ ; 方法一 第四步:hMenu (覆盖WNDCLASSEX结构体中指定的菜单) 。 方法二:使NULL
hInst,\
NULL
mov hwnd,eax
invoke ShowWindow,hwnd,CmdShow
invoke UpdateWindow,hwnd
.while TRUE
invoke GetMessage,addr msg,NULL,0,0
.break .if eax==0
invoke TranslateAccelerator,hwnd,hAccelerator,addr msg
;TranslateAccelerator是实现加速键功能的关键,
;该函数检查消息结构中的消息,如果WM_KEYDOWN或WM_SYSKEYDOWN有效
;则Windows再检查加速键资源,查看按键是否符合某个加速键
;若符合,则windows向目标窗口发送WM_COMMAND或WM_SYSCOMMAND
;消息,并返回true 若不符合则不做任何处理,并返回FALSE
.if eax==0
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endif
.endw
mov eax,msg.wParam
ret
WinMain endp
start:
invoke GetModuleHandle,NULL ;创建窗口第一步:得到应用程序的句柄
mov hInstance,eax
invoke LoadAccelerators,hInstance,IDA_ACCELERATOR ;要先LoadAccelerators???
mov hAccelerator,eax
invoke LoadMenu,hInstance,IDM_MAIN ;第二步:使用LoadMenu和LoadAccelerator函数加载菜单和加速键
mov hMenu,eax
invoke WinMain,hInstance,NULL,NULL,SW_SHOWDEFAULT
invoke ExitProcess,eax
end start
.rc资源文件如下:
#include<resource.h>
#define IDD_Caption 129
#define IDCANCEL 2
#define IDOK 1
#define IDC_Caption 1000
#define IDC_STATIC -1
IDD_Caption DIALOG DISCARDABLE 100,100,173,60
STYLE DS_MODALFRAME|WS_VISIBLE|WS_CAPTION|WS_SYSMENU
CAPTION "标题栏文字"
FONT 10,"System"
BEGIN
DEFPUSHBUTTON "取消(&c)",IDCANCEL,106,39,37,13,WS_GROUP
EDITTEXT IDC_Caption,12,21,146,12,ES_AUTOHSCROLL
LTEXT "请在此输入文字",IDC_STATIC,11,11,105,9
DEFPUSHBUTTON "确定(&k)",IDOK,53,39,37,13,WS_GROUP
END