使用Win32 ASM制作一个窗口菜单;
资源文件;
#define ICO_MAIN 0x1000 //图标
#define IDM_MAIN 0x2000 //菜单
#define IDM_HELP 0x4301
#define IDM_ABOUT 0x4302
#define IDM_ADDWZ 0x5001
#define IDM_UPDATEWZ 0x5002
#define IDM_DELWZ 0x5003
#define IDM_QUERYWZ 0x5004
#define IDM_ADDCK 0x6001
#define IDM_UPDATECK 0x6002
#define IDM_DELCK 0x6003
#define IDM_QUERYCK 0x6004
ICO_MAIN ICON "Main.ico"
IDM_MAIN menu discardable
BEGIN
popup "物资信息"
BEGIN
menuitem "添加物资", IDM_ADDWZ
menuitem "更新物资", IDM_UPDATEWZ
menuitem "删除物资", IDM_DELWZ
menuitem separator
menuitem "查询物资", IDM_QUERYWZ
END
popup "仓库信息"
BEGIN
menuitem "添加仓库", IDM_ADDCK
menuitem "更新仓库", IDM_UPDATECK
menuitem "删除仓库", IDM_DELCK
menuitem separator
menuitem "查询仓库", IDM_QUERYCK
END
popup "帮助" ,HELP
BEGIN
menuitem "帮助主题", IDM_HELP
menuitem separator
menuitem "关于本程序...",IDM_ABOUT
END
END
asm文件;
; Win32 菜单 Demo,by bobo
.386
.model flat, stdcall
option casemap :none
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
; Equ 等值定义
ICO_MAIN equ 1000h ;图标
IDM_MAIN equ 2000h ;菜单
IDM_HELP equ 4301h
IDM_ABOUT equ 4302h
IDM_ADDWZ equ 0x5001
IDM_UPDATEWZ equ 0x5002
IDM_DELWZ equ 0x5003
IDM_QUERYWZ equ 0x5004
IDM_ADDCK equ 0x6001
IDM_UPDATECK equ 0x6002
IDM_DELCK equ 0x6003
IDM_QUERYCK equ 0x6004
; 数据段
.data?
hInstance dd ?
hWinMain dd ?
hMenu dd ?
; 数据段
.const
szClassName db 'MIS Menu Demo',0
szCaptionMain db 'MIS Menu ',0
szMenuHelp db '帮助主题',0
szMenuAbout db '关于本程序...',0
szCaption db '菜单选择',0
szFormat db '您选择了菜单命令:%08x',0
; 代码段
.code
_DisplayMenuItem proc _dwCommandID
local @szBuffer[256]:byte
pushad
invoke wsprintf,addr @szBuffer,addr szFormat,_dwCommandID
invoke MessageBox,hWinMain,addr @szBuffer,offset szCaption,MB_OK
popad
ret
_DisplayMenuItem endp
_Quit proc
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
ret
_Quit endp
_ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam
mov eax,uMsg
.if eax == WM_CREATE
.elseif eax == WM_COMMAND
invoke _DisplayMenuItem,wParam
.elseif eax == WM_CLOSE
call _Quit
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
;********************************************************************
xor eax,eax
ret
_ProcWinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
local @stWndClass:WNDCLASSEX
local @stMsg:MSG
local @hAccelerator
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke LoadMenu,hInstance,IDM_MAIN
mov hMenu,eax
;********************************************************************
; 注册窗口类
;********************************************************************
invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
invoke LoadIcon,hInstance,ICO_MAIN
mov @stWndClass.hIcon,eax
mov @stWndClass.hIconSm,eax
invoke LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance
pop @stWndClass.hInstance
mov @stWndClass.cbSize,sizeof 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
invoke RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE,\
offset szClassName,offset szCaptionMain,\
WS_OVERLAPPEDWINDOW,\
100,100,400,300,\
NULL,hMenu,hInstance,NULL
mov hWinMain,eax
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain
;********************************************************************
; 消息循环
;********************************************************************
.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax == 0
invoke TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg
.if eax == 0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endif
.endw
ret
_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call _WinMain
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
命令行构建:
G:\win32ASM\MISMenuDemo>set include=g:\masm32\include
G:\win32ASM\MISMenuDemo>set lib=g:\masm32\lib
G:\win32ASM\MISMenuDemo>set path=g:\masm32\bin;%path%
G:\win32ASM\MISMenuDemo>ml /c /coff wz.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: wz.asm
***********
ASCII build
***********
G:\win32ASM\MISMenuDemo>rc wz.rc
G:\win32ASM\MISMenuDemo>Link /subsystem:windows wz.obj wz.res
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
G:\win32ASM\MISMenuDemo>
结果;
资源文件里使用popup定义一个下拉出来的菜单项,下拉出来的菜单项包含在BEGIN...END里面,使用menuitem定义一个菜单项;
汇编代码有2个子过程;_DisplayMenuItem,显示单击的菜单标识值;_Quit,退出;
在主对话框过程里啥也没干;当单击菜单,收到WM_COMMAND消息,执行
invoke _DisplayMenuItem,wParam
显示单击的菜单标识值;
在资源文件里面定义了各菜单标识的值;在asm文件里面又定义了等值equ定义;这是啥情况;为什么要定义2次呢;云彬兄的Win32汇编程序里面也都包含这个equ等值定义;
搞C的时候,一般在resource.h文件里定义资源标识的值,然后包含resource.h就可以了;
因为汇编的时候各是各的,使用ml命令把asm汇编为obj文件时需要资源标识的值;rc文件是单独编译;使用rc命令把.rc文件编译为.RES文件的时候,也需要资源标识的值;这两次各是各的;
所以需要等值定义;只是在asm集成开发环境里,ml和rc它一次帮你执行了;代码里是需要equ定义的;
此处,消息循环里,
invoke TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg
这句不能删除;