把菜单资源文件定义的ID复制过来修改一下
.data ?
CreateWindowEx 第10个参数填上
.elseif eax == WM_RBUTTONDOWN ;右键被按下
invoke GetCursorPos,addr stPos ;获取鼠标位置 addr 获取变量地址
invoke TrackPopupMenu,hSubMenu,TPM_LEFTALIGN,stPos.x,stPos.y,0,hWnd,0 ;弹出菜单
IDM_MAIN equ 1
IDM_NEW equ 101
IDM_OPEN equ 102
IDM_SAVA equ 103
IDM_EXIT equ 104
IDM_CUT equ 201
IDM_COPY equ 202
IDM_PASTE equ 203
IDM_ABOUT equ 301
IDM_ADD equ 401
.data ?
hMenu dd ? ;菜单句柄
在
.if eax == WM_CLOSE ;关闭按钮
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
下面加上
.elseif eax == WM_COMMAND ;区分消息来源ID,快捷键还是菜单
mov eax,wParam
.if eax == IDM_EXIT ;退出
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
.elseif eax == IDM_ABOUT ;关于
invoke MessageBox,0,NULL,NULL,MB_OK ;要执行的代码
.endif
invoke CreateWindowEx上面加入
invoke LoadMenu,hInstance,IDM_MAIN ;载入菜单
mov hMenu,eax ;把句柄放到hMenu
CreateWindowEx 第10个参数填上
hMenu
用MASMPlus编译,资源文件rc必须和代码asm文件同名.
1.rc文件
#include <resource.h>
#define IDM_MAIN 1
#define IDM_NEW 101
#define IDM_OPEN 102
#define IDM_SAVA 103
#define IDM_EXIT 104
#define IDM_CUT 201
#define IDM_COPY 202
#define IDM_PASTE 203
#define IDM_ABOUT 301
#define IDM_ADD 401
IDM_MAIN MENU DISCARDABLE
BEGIN
POPUP "文件"
BEGIN
MENUITEM "新建", IDM_NEW
MENUITEM "打开", IDM_OPEN
MENUITEM "保存", IDM_SAVA
menuitem separator
MENUITEM "退出", IDM_EXIT
END
POPUP "编辑"
BEGIN
MENUITEM "剪切", IDM_CUT
MENUITEM "复制", IDM_COPY
MENUITEM "粘贴", IDM_PASTE
END
POPUP "帮助"
BEGIN
MENUITEM "关于", IDM_ABOUT
END
END
1.asm
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;所有API函数的返回值保存在eax
IDM_MAIN equ 1
IDM_NEW equ 101
IDM_OPEN equ 102
IDM_SAVA equ 103
IDM_EXIT equ 104
IDM_CUT equ 201
IDM_COPY equ 202
IDM_PASTE equ 203
IDM_ABOUT equ 301
IDM_ADD equ 401
.data?
hMenu dd ? ;菜单句柄
hInstance DD ?
hWinMain DD ?
.data
.const
szClassName DB 'MyClass',0
szCaptionMain DB '标题',0
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 响应用户操作
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
mov eax,uMsg
;*************************可修改**************************
.if eax == WM_CLOSE ;关闭按钮
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
.elseif eax == WM_COMMAND ;区分消息来源ID,快捷键还是菜单
mov eax,wParam
.if eax == IDM_EXIT ;退出
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
.elseif eax == IDM_ABOUT ;关于
invoke MessageBox,0,NULL,NULL,MB_OK ;要执行的代码
.endif
;下面 .elseif eax == ******
; 需要执行的代码
;例如
; .elseif eax == WM_LBUTTONDOWN ;鼠标左键被按下
; invoke MessageBox,0,NULL,NULL,MB_OK ;弹出信息框
;*************************可修改**************************
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
_ProcWinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; _WinMain子过程——好戏开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
local @stWndClass:WNDCLASSEX ;定义stWndClass类结构为WNDCLASSEX
local @stMsg:MSG
invoke GetModuleHandle,NULL ;获取应用程序句柄
mov hInstance,eax ;窗口句柄保存在hInstance
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass ;初始类内容为0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 注册窗口类
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
invoke LoadCursor,0,IDC_ARROW ;载入光标
mov @stWndClass.hCursor,eax ;载入光标
push hInstance
pop @stWndClass.hInstance ;应用程序句柄
mov @stWndClass.cbSize,sizeof WNDCLASSEX ;获取WNDCLASSEX结构大小,这段不用改
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW ;窗口风格
mov @stWndClass.lpfnWndProc,offset _ProcWinMain ;响应用户操作,这段不用改
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1 ;句柄画刷
mov @stWndClass.lpszClassName,offset szClassName ;这个类名字为szClassName
invoke RegisterClassEx,addr @stWndClass ;注册这个窗口类
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 建立并显示窗口
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
invoke LoadMenu,hInstance,IDM_MAIN ;载入菜单
mov hMenu,eax ;把句柄放到hMenu
invoke CreateWindowEx,NULL,\ ;扩展
offset szClassName,\ ;@stWndClass类的名字
offset szCaptionMain,\ ;标题
WS_OVERLAPPEDWINDOW,\ ;窗口类型
100,100,\ ;X,Y坐标
600,400,\ ;窗口宽度,窗口高度
NULL,\ ;父窗口句柄
hMenu,\ ;菜单句柄
hInstance,\ ;应用程序的句柄
NULL
mov hWinMain,eax ;保存CreateWindowEx创建出来的句柄
invoke ShowWindow,hWinMain,SW_SHOWNORMAL;显示出来的样式
invoke UpdateWindow,hWinMain ;可加可不加
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 消息循环,不用修改
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax == 0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
ret
_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 程序入口
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call _WinMain ;调用_WinMain子过程
invoke ExitProcess,NULL
end start
2 右键弹出菜单
在.data ?加入
hSubMenu dd?
在_ProcWinMain子过程添加局部变量
local stPos:POINT
.elseif eax == WM_CREATE ;WM_CREATE是窗口创建CreateWindow时,系统给消息处理程序发送的消息,每次窗口创建,有且只有1个WM_CREATE消息,所以只运行1次,可以在这里初始化滚动条,获取字体宽度、高度,创建子窗口、控件等等。
invoke GetSubMenu,hMenu,0 ;获取子菜单 0代表第一个菜单项(RC里面的第一个POPUP里面的内容)
mov hSubMenu,eax ;子菜单句柄保存在hSubMenu
.elseif eax == WM_RBUTTONDOWN ;右键被按下
invoke GetCursorPos,addr stPos ;获取鼠标位置 addr 获取变量地址
invoke TrackPopupMenu,hSubMenu,TPM_LEFTALIGN,stPos.x,stPos.y,0,hWnd,0 ;弹出菜单