.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