这篇博文将会简单介绍下菜单、图标与光标在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
三、代码中图标与光标文件下载
四、关于本篇博文的例子
程序运行起来后,选择菜单中的项目可以看到图标与光标的改变。