您的位置:首页 > 其它

《Windows环境下32位汇编语言程序设计(第2版)》-chapter5-基本框架

2016-07-24 20:11 330 查看
第五章开始创建一个带菜单的窗口,自己把代码打出来又做了注释,只是粘贴到代码段后格式有点乱,对齐什么的,强迫症飘过,暂时没找到好办法整理或者避免……

菜单的资源文件(资源文件的后缀是rs,只是CSDN无法识别这个,就改成txt了)

# include
# define IDM_MAIN		 0x2000
# define IDA_MAIN		 0x2000

# define IDM_OPEN		 0x4101
# define IDM_OPTION		 0x4102
# define IDM_EXIT		 0x4103
# define IDM_SETFONT	 0x4201
# define IDM_SETCOLOR	 0x4202
# define IDM_INACT		 0x4203
# define IDM_GRAY		 0x4204
# define IDM_BIG		 0x4205
# define IDM_SAMLL		 0x4206
# define IDM_LIST		 0x4207
# define IDM_DETAIL		 0x4208

# define IDM_TOOLBAR	 0x4209
# define IDM_TOOLBARTEXT 0x4210
# define IDM_INPUTBAR	 0x4211
# define IDM_STATUSBAR   0x4212

# define IDM_HELP		 0x4301
# define IDM_ABOUT		 0x4302

IDM_MAIN	menu		discardable
BEGIN
popup	"文件(&F)"
BEGIN
menuitem 	"打开文件(&O)", IDM_OPEN
menuitem	"关闭文件(&C)", IDM_OPTION
menuitem	separator
menuitem	"退出(&X)", IDM_EXIT
END

popup	"查看(&V)"
BEGIN
menuitem	"字体(&F)\tAlt+F", IDM_SETFONT			//&表示在字母下面添加下划线,默认为快捷键
menuitem	"背景色(&B)\tCtrl+Alt+B", IDM_SETCOLOR //\t会使后面的字符串右对齐
menuitem	separator
menuitem	"被禁用的菜单项", IDM_INACT, INACTIVE	//CHECKED,GRAYED,INACTIVE,MENUBREAK,MENUBARBREAK(以下部分另起一列)
menuitem	"被灰化的菜单项", IDM_GRAY, GRAYED
menuitem	separator
menuitem	"大图标(&G)", IDM_BIG
menuitem	"小图标(&M)", IDM_SAMLL
menuitem	"列表(&L)", IDM_LIST
menuitem	"详细资料(&D)", IDM_DETAIL
menuitem	separator
popup	"工具栏(&T)"
BEGIN
menuitem	"标准按钮(&S)", IDM_TOOLBAR
menuitem	"文字标签(&C)", IDM_TOOLBARTEXT
menuitem	"命令栏(&T)", IDM_INPUTBAR
menuitem	"状态栏(&U)", IDM_STATUSBAR
END
END

popup	"帮助(&H)"										 //popup ”” [,GRAYED][,INACTIVE][,HELP(右对齐)]
BEGIN
menuitem	"帮助主题(&H)", IDM_HELP
menuitem	separator
menuitem	"关于本程序(&A)", IDM_ABOUT
END
END

IDA_MAIN accelerators
BEGIN
VK_F1, IDM_HELP, VIRTKEY									//"^X" = ctrl + X
"B", IDM_SETCOLOR, VIRTKEY, CONTROL, ALT					//"X" = X, VIRTKEY
"F", IDM_SETFONT, VIRTKEY, ALT								//数值	表示Ascii为该数值的字母,ASCII
//[,CONTROL][,ALT][,SHIFT]
//VK_F1 = F1
//VK_BACK
//VK_ESCAPE
//VK_DELETE
//VK_RETURN
END


主程序文件

.386
.model flat, stdcall
option casemap: none
;-----------------------------------------------------------------------
include		  	windows.inc
include		  	gdi32.inc
includelib 	  	gdi32.lib
include 	  	user32.inc
includelib	  	user32.lib
include 	  	kernel32.inc
includelib    	kernel32.lib
;-----------------------------------------------------------------------
IDM_MAIN		equ	2000h
IDA_MAIN		equ 2000h

IDM_OPEN		equ 	4101h
IDM_OPTION		equ 	4102h
IDM_EXIT		equ 	4103h
IDM_SETFONT	 	equ 	4201h
IDM_SETCOLOR	equ 	4202h
IDM_INACT		equ 	4203h
IDM_GRAY		equ 	4204h
IDM_BIG		 	equ 	4205h
IDM_SAMLL		equ 	4206h
IDM_LIST		equ 	4207h
IDM_DETAIL		equ 	4208h

IDM_TOOLBAR	 	equ 	4209h
IDM_TOOLBARTEXT equ 	4210h
IDM_INPUTBAR	equ 	4211h
IDM_STATUSBAR   equ 	4212h

IDM_HELP		equ 	4301h
IDM_ABOUT		equ 	4302h
;-----------------------------------------------------------------------
.data
hInstance 	  	dd 		?
hWinMain  	  	dd 		?
hMenu   	  	dd 		?
hSubMenu  	  	dd 		?
.const
szClassName   	db 		'MyClass', 0
szCaptionMain 	db 		'My first window', 0
szText		  	db 		'Win32 Assemply, Simple and powerful!', 0
szMenuHelp		db		'帮助主题(&H)', 0
szMenuAbout		db		'关于本程序(&A)', 0
szCaption 		db		'MenuDisply', 0
szFormat		db 		'what you choose is:%08x', 0					;@08x最少8位的16进制
;-----------------------------------------------------------------------
.code
;-----------------------------------------------------------------------
;_DisplayMenuItem实现弹出一个指定格式内容的窗口
;-----------------------------------------------------------------------
_DisplayMenuItem 		proc 	_dwCommandID							;_dwCommandID是形式参数,此处未指明类型
local 	@szBuffer[256]: byte

pushad													;保护现场
invoke 	wsprintf, addr @szBuffer, addr szFormat,\		;wsprintf(szBuffer, szFormat, _dwCommandID);
_dwCommandID									;wParam有32位,低16位是命令id(资源ID),高16位是通知码,全0为菜单消息,全1为快捷键消息
invoke 	MessageBox, hWinMain, addr @szBuffer, \			;MessageBox(hWinMain, szBuffer, szCaption, MB_OK);
offset szCaption, MB_OK							;			模块句柄,显示内容,窗口标题,窗口模式
popad													;保护现场
ret														;相当于return,自动实现堆栈平衡

_DisplayMenuItem 		endp
;-----------------------------------------------------------------------
;_Quit单独实现了退出功能,可以再加上一些判断。利用call调用即可
;-----------------------------------------------------------------------
_Quit 			proc

invoke 	DestroyWindow, hWinMain							;DestroyWindow(hWndMain);销毁窗口
invoke 	PostQuitMessage, 0								;PostQuitMessage(0);	 终止进程
ret

_Quit			endp
;-----------------------------------------------------------------------
_ProcWinMain    proc  	uses ebx edi esi, hWnd, uMsg, wParam, lParam
local 	@stPs: PAINTSTRUCT
local 	@stRect: RECT
local 	@hDc
local 	@stPos: POINT
local 	@hSysMenu

mov 	eax, uMsg											;载入消息
;-----------------------------------------------------------
.if   	eax == WM_PAINT										;感兴趣的自己处理
invoke  BeginPaint, hWnd, addr @stPs
mov	    @hDc, eax

invoke  GetClientRect, hWnd, addr @stRect
invoke  DrawText, @hDc, addr szText, -1,\
addr @stRect,\
DT_SINGLELINE or DT_CENTER or DT_VCENTER

invoke  EndPaint, hWnd, addr @stPs
;-----------------------------------------------------------
.elseif eax == WM_CREATE
;为了右键菜单使用,实际上应该自己定义一个
invoke 	GetSubMenu, hMenu, 1
mov		hSubMenu, eax

;在系统菜单中添加自己的菜单(右键标题栏)
;此菜单发送WM_SYSCOMMAND
;invoke 	GetSystemMenu, hWnd, FALSE
;mov		@hSysMenu, eax
;invoke 	AppendMenu, @hSysMenu, MF_SEPARATOR, 0, NULL
;invoke 	AppendMenu, @hSysMenu, 0, IDM_HELP, offset szMenuHelp
;invoke 	AppendMenu, @hSysMenu, 0, IDM_ABOUT, offset szMenuAbout

;-----------------------------------------------------------
.elseif eax == WM_COMMAND									;用户选择一个菜单项(非系统菜单),用户按下一个快捷键(非系统键),都处理成返回到主窗口处理
;通知用户按下菜单的ID----------------------------
invoke 	_DisplayMenuItem, wParam					;wParam里保存着通知码和ID值(菜单项和对应的快捷键返回同一个wParam)
;WM_COMMAND就是这样定义的
;取出ID,进行判断----------------------------------
mov		eax, wParam
movzx 	eax, ax
.if		eax == IDM_EXIT
call 	_Quit
.endif
;-----------------------------------------------------------
.elseif eax == WM_SYSCOMMAND								;用户选择一个系统菜单,用户按下一个系统快捷键,都处理成返回到主窗口处理
;取出ID,进行判断----------------------------------
mov		eax, wParam
movzx 	eax, ax
.if 	eax == IDM_HELP || eax == IDM_ABOUT
invoke 	_DisplayMenuItem, wParam
.else												;除了系统快捷键和自己定义的系统菜单外,其他交给系统去处理,一下为套路
invoke 	DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.endif
;-----------------------------------------------------------
.elseif eax == WM_RBUTTONDOWN
;BOOL GetCursorPos(LPPOINT lpPoint);
;把光标所在坐标存入POINT中
invoke 	GetCursorPos, addr @stPos
;BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, CONST RECT* prcRect);
;hMenu:此句柄可为调用CreatePopupMenu创建的新快捷菜单的句柄,也可以为调用GetSubMenu取得的与一个已存在菜单项相联系的子菜单的句柄。
;uFlags:TPM_CENTERALIGN:x居中放置,TPM_LEFTALIGN:左边界与X对齐,TPM_RIGHTALIGN:右边界与X对齐
;NReserved:保留值,必须为零
;HWnd:拥有快捷菜单的窗口的句柄,hInstance,在_ProcWinMain中是hWnd
;prcRect:NULL,在菜单外单击菜单消失
invoke 	TrackPopupMenu, hSubMenu, TPM_LEFTALIGN, @stPos.x, @stPos.y, 0, hWnd, NULL
;-----------------------------------------------------------
.elseif eax == 	WM_CLOSE									;套路
;invoke 	DestroyWindow, hWinMain
;invoke 	PostQuitMessage, NULL
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	;获取本模块句柄存入eax中
mov		hInstance, eax			;存入全局变量hInstance中
;获取菜单句柄---------------------------------------------
;HMENU LoadMenu(HINSTANCE hlnstance,LPCTSTR lpMenuName);
;若函数调用成功,则返回所加载的菜单句柄,若函数调用失败,则返回值为NULL
;hlnstance:含有被加载菜单资源的实例模块的句柄
;LpMenuName:低位字16bit资源标识符,高位字16bit全零
;-----------------------------------------------------------
invoke 	LoadMenu, hInstance, IDM_MAIN						;必须获取菜单句柄
mov 	hMenu, eax
;获取快捷键句柄-------------------------------------------
;HACCEL LoadAccelerators(HINSTANCE hlnstance,LPCTSTR lpTableName);
;lpTableName:低位字16bit资源标识符,高位字16bit全零
;-----------------------------------------------------------
invoke 	LoadAccelerators, hInstance, IDA_MAIN				;必须获取快捷键句柄
mov 	@hAccelerator, eax									;必须改写消息循环
;-----------------------------------------------------------

invoke 	RtlZeroMemory, addr @stWndClass, sizeof @stWndClass ;必须初始化局部变量
;															;hIcon!!!
;															;hCursor!!!
;															;lpszMenuName!!!
push 	hInstance											;hInstance
pop		@stWndClass.hInstance
mov 	@stWndClass.cbSize, sizeof WNDCLASSEX				;cbsize
mov 	@stWndClass.style, CS_HREDRAW or CS_VREDRAW			;style!!!
mov 	@stWndClass.lpfnWndProc, offset _ProcWinMain		;lpfnWndProc
mov 	@stWndClass.hbrBackground, COLOR_WINDOW + 1			;hbrBackground!!!
mov 	@stWndClass.lpszClassName, offset szClassName		;lpszClassName
;															;cbWndExtra
;															;cbClsExtra
invoke 	RegisterClassEx, addr @stWndClass					;stWndClass是一个结构体
;-----------------------------------------------------------
;创建窗口--------------------------------------------------
invoke 	CreateWindowEx, WS_EX_CLIENTEDGE,\					;dwExStyle!!!
offset szClassName, offset szCaptionMain,\			;lpClassName, lpWindowMain
WS_OVERLAPPEDWINDOW,\								;dwStyle!!!
100, 100, 600, 400,\								;x, y, nWight, nHeight
NULL, hMenu, hInstance, NULL						;hWndParent!!!, hMenu!!!, hInstance, lpParam!!!
mov 	hWinMain, eax
;显示窗口--------------------------------------------------
invoke 	ShowWindow, hWinMain, SW_SHOWNORMAL					;SW!!!
;更新窗口--------------------------------------------------
invoke 	UpdateWindow, hWinMain
;-----------------------------------------------------------
;消息循环--------------------------------------------------
;|--------------------------------------------------------------------------------------------------------------|
;|.while 	TRUE																							   	|
;|		invoke GetMessage, addr @stMsg, NULL, 0, 0			;lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax			|
;|															;addr @stMsg										|
;|															;hWnd NULL 本程序所属窗口							|
;|															;wMsgFilterMax = wMsgFilterMin = 0 获取所有消息 	|
;|		.break .if eax == 0									;WM_QUIT eax = 0, 退出消息循环					|
;|		invoke TranslateMessage, addr @stMsg				;WM_CHAR, WM_SYSCHAR, 键盘消息转换					|
;|		invoke DispatchMessage, addr @stMsg					;发送到窗口过程函数								|
;|.endw																											|
;|--------------------------------------------------------------------------------------------------------------|
.while 	TRUE
invoke 	GetMessage, addr @stMsg, NULL, 0, 0
.break 	.if eax == 0

;系统自动完成快捷键检测功能----------------------
;int TranslateAccelerator(HWND hWnd,HACCEL hAccTable,LPMSG IpMsg);
;若函数调用成功,则返回非零值;若函数调用失败,则返回值为零(没找到快捷键的消息)
;hWnd:消息被发送到这个窗口处理
;hAccTable:快捷键表句柄
;lpMsg:从GetMessage或PeekMessage从消息队列获取的消息
;---------------------------------------------------
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
;-----------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows 32位 汇编