第三篇 菜单、图标与光标的使用

这篇博文将会简单介绍下菜单、图标与光标在Windows窗口程序中如何使用。

 

一、菜单、图标、光标都是作为资源在资源文件中定义的。

1、菜单的定义方法:

菜单ID  MENU  [DISCARDABLE]

BEGIN

            菜单项定义

END

 

菜单项定义:

定义普通菜单项:

MENUITEM  菜单文字 ,命令ID  [,选项列表]

定义分割线:

MENUITEM  SEPARATOR

定义弹出式菜单:

POPUP  菜单文字  [,选项列表]

BEGIN

           菜单项定义

END

 

2、图标与光标的定义

图标ID  ICON  [DISCARDABLE]   图标文件名

光标ID  CURSOR  [DISCARDABLE]   光标文件名

 

3、注意

所谓的XXID都是用户自定义的一些数值,范围是0~0FFFFH

DISCARDABLE是内存选项,表示在不用时可以自动释放内存

 

4、例子

#include <resource.h>

//菜单选项
#define	IDM_MAIN	0x1000
#define IDM_ICOHEAD	0x2000
#define	IDM_ICOARROW	0x2001
#define	IDM_CURDINOSAUR	0x2002
#define	IDM_CURHAND	0x2003

//图标
#define	ICON_HEAD	0x3000
#define ICON_ARROW	0x3001

//光标
#define	CUR_HAND	0x4000

ICON_ARROW	icon	discardable "Arrow.ico"
ICON_HEAD	icon	discardable "Head.ico"
CUR_HAND	cursor	discardable "Hand.cur"

IDM_MAIN	menu	discardable
BEGIN
		popup	"图标与光标选项(&C)..."
		BEGIN
			menuitem	"头像图标",	IDM_ICOHEAD
			menuitem	"箭头图标",	IDM_ICOARROW
			menuitem	separator
			menuitem	"恐龙光标",	IDM_CURDINOSAUR
			menuitem	"手掌光标",	IDM_CURHAND
		END
END

 

二、在主窗口程序中使用菜单、图标、光标资源

1、如何建立窗口:第二篇 第一个窗口程序

 

2、使用方法

①使用菜单

首先,在获得模块句柄后将菜单(由菜单ID—IDM_MAIN指定)加载进应用程序

		invoke	GetModuleHandle,NULL
		mov	hInstance,eax
		invoke	LoadMenu,hInstance,IDM_MAIN
		mov	hMenu,eax

其次,在建立窗口时将菜单句柄hMenu作为参数传递进去

		invoke	CreateWindowEx,WS_EX_CLIENTEDGE,\
			offset szClassName,offset szClassName,\
			WS_OVERLAPPEDWINDOW,\
			200,200,300,200,\
			NULL,hMenu,hInstance,NULL


②使用光标与图标的方法

在调用CreateWindowEx建立窗口时,在函数返回前系统会向窗口程序发出WM_CREATE消息。我们可以

此时加载光标与图标资源。然后紧接着调用SendMessage函数将缺省建立的图标与光标类型发送给窗口程

序处理。

		.if	eax == WM_CREATE
			invoke	LoadIcon,hInstance,ICON_HEAD
			mov	hIconHead,eax
			invoke	LoadIcon,hInstance,ICON_ARROW
			mov	hIconArrow,eax
			invoke	LoadCursor,hInstance,CUR_HAND
			mov	hCurHand,eax
			invoke	LoadCursorFromFile,addr szCursorFile
			mov	hCurDinosaur,eax
			invoke	SendMessage,hWnd,WM_COMMAND,IDM_ICOHEAD,NULL
			invoke	SendMessage,hWnd,WM_COMMAND,IDM_CURHAND,NULL

 

3、例子

.386
.model flat,stdcall
option casemap:none

include		windows.inc
include		user32.inc
includelib	user32.lib
include		kernel32.inc
includelib	kernel32.lib

;下面的equ定义千万不要写成0x...
;菜单ID的定义
IDM_MAIN	equ	1000h
IDM_ICOHEAD	equ	2000h
IDM_ICOARROW	equ	2001h
IDM_CURDINOSAUR	equ	2002h
IDM_CURHAND	equ	2003h

;图标ID的定义
ICON_HEAD	equ	3000h
ICON_ARROW	equ	3001h

;静态光标文件的定义
CUR_HAND	equ	4000h

;句柄定义
.data?
hInstance	dd	?
hMenu		dd	?
hWinMain	dd	?
hCurDinosaur	dd	?
hCurHand	dd	?
hIconHead	dd	?
hIconArrow	dd	?

.const
szCursorFile	db	'Dinosaur.ani',0     ;存储于磁盘上的动态光标文件        
szClassName	db	'Icon and Cursor!',0

.code
_Quit		proc
		invoke	DestroyWindow,hWinMain
		invoke	PostQuitMessage,NULL
		ret
_Quit		endp

_WinMainProc	proc	uses ebx edi esi hWnd,uMsg,wParam,lParam
		mov	eax,uMsg

		.if	eax == WM_CREATE
			invoke	LoadIcon,hInstance,ICON_HEAD
			mov	hIconHead,eax
			invoke	LoadIcon,hInstance,ICON_ARROW
			mov	hIconArrow,eax
			invoke	LoadCursor,hInstance,CUR_HAND
			mov	hCurHand,eax
			invoke	LoadCursorFromFile,addr szCursorFile
			mov	hCurDinosaur,eax
			invoke	SendMessage,hWnd,WM_COMMAND,IDM_ICOHEAD,NULL
			invoke	SendMessage,hWnd,WM_COMMAND,IDM_CURHAND,NULL
		.elseif	eax == WM_COMMAND
			mov	eax,wParam
			movzx	eax,ax
			.if	eax == IDM_ICOHEAD
				;ICON_BIG是WM_SETICON中预定义的
				invoke	SendMessage,hWnd,WM_SETICON,ICON_BIG,hIconHead     
				invoke	CheckMenuRadioItem,hMenu,IDM_ICOHEAD,IDM_ICOARROW,\
					IDM_ICOHEAD,MF_BYCOMMAND
			.elseif	eax == IDM_ICOARROW
				;ICON_SMALL是WM_SETICON中预定义的
				invoke	SendMessage,hWnd,WM_SETICON,ICON_SMALL,hIconArrow    
				invoke	CheckMenuRadioItem,hMenu,IDM_ICOHEAD,IDM_ICOARROW,\
					IDM_ICOARROW,MF_BYCOMMAND
			.elseif	eax == IDM_CURDINOSAUR
				invoke	SetClassLong,hWnd,GCL_HCURSOR,hCurDinosaur
				invoke	CheckMenuRadioItem,hMenu,IDM_CURDINOSAUR,IDM_CURHAND,\
					IDM_CURDINOSAUR,MF_BYCOMMAND
			.elseif	eax == IDM_CURHAND
				invoke	SetClassLong,hWnd,GCL_HCURSOR,hCurHand
				invoke	CheckMenuRadioItem,hMenu,IDM_CURDINOSAUR,IDM_CURHAND,\
					IDM_CURHAND,MF_BYCOMMAND
			.endif
		.elseif	eax == WM_CLOSE
			invoke	_Quit
		.else
			invoke	DefWindowProc,hWnd,uMsg,wParam,lParam
			ret
		.endif

		mov	eax,0
		ret
_WinMainProc	endp

_WinMain	proc
		local	@stWndClass:WNDCLASSEX
		local	@stMsg:MSG

		invoke	GetModuleHandle,NULL
		mov	hInstance,eax
		invoke	LoadMenu,hInstance,IDM_MAIN
		mov	hMenu,eax

		invoke	RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
		push	hInstance
		pop	@stWndClass.hInstance
		mov	@stWndClass.cbSize,sizeof @stWndClass
		mov	@stWndClass.style,CS_HREDRAW or CS_VREDRAW
		mov	@stWndClass.lpfnWndProc,offset _WinMainProc
		mov	@stWndClass.hbrBackground,COLOR_WINDOW + 1
		mov	@stWndClass.lpszClassName,offset szClassName
		invoke	RegisterClassEx,addr @stWndClass

		invoke	CreateWindowEx,WS_EX_CLIENTEDGE,\
			offset szClassName,offset szClassName,\
			WS_OVERLAPPEDWINDOW,\
			200,200,300,200,\
			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	TranslateMessage,addr @stMsg
			invoke	DispatchMessage,addr @stMsg
		.endw

		ret
_WinMain	endp

start:
		invoke	_WinMain
		invoke	ExitProcess,NULL
		
		end	start

三、代码中图标与光标文件下载

图标与光标文件

 

四、关于本篇博文的例子

程序运行起来后,选择菜单中的项目可以看到图标与光标的改变。

 

 

你可能感兴趣的:(第三篇 菜单、图标与光标的使用)