资源文件以rc为扩展名的脚本文件,Rc.exe编译成res二进制资源文件,Link.exe链入可执行文件中。

一、菜单和加速键

1、菜单的定义

在资源脚本文件中菜单的定义格式:

菜单 ID MENU [DISCARDABLE]//指定菜单ID值和内存属性,ID范围1~65535大于10000h当做 //字符串指针处理

BEGIN

菜单项定义

```

END

菜单项目的定义方法有3类:

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

或 MENUITEM SEPAPATOR

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

BEGIN

item-definitions

```

END

MENUITEM 菜单文字 , 命令ID [,选项列表] 方法1:

菜单文字:在字母前加&是下划线,带下划线的字母被系统自动当做快捷键。“字体(&F)...\tAlt+F”这样加入\t  tab字符后面的字符在显示的时候会有对齐。

命令ID:菜单被选中的时候,Windows会向窗口过程发送WM_COMMAND消息,消息的参数就是选中的命令ID。

选项:用来定义菜单的各种属性,可以是以下数值:

CHECKED---------表示打钩。

CGAYED-----------灰色

INACTIVE---------禁用

MENUBREAK或MENUBARBREAK------这个菜单项起(包括以后菜单项)到新列中。

MENUITEM SEPAPATOR方法2:是菜单直接的分隔线。

POPUP 菜单文字 [,选项列表]方法3:

是弹出菜单,popup菜单的选项列表可以是以下值:

CGAYED-----------灰色

INACTIVE---------禁用

HELP-------表示本项和以后的菜单项目是右对齐,如帮助菜单。

弹出参数不需要ID选中自动弹出。

有些定义是可以同时定义的,中间用逗号隔开,但是GRAYED和INACTIVE不能同时使用,MENUBREAK和MENUBARBREAK也是不能同时使用。

2、加速键的定义

定义格式:

加速键  ID  ACCELERATORS

BEGIN

键名 , 命令ID  [,类型]  [,选项]

···

END

加速键资源ID定义范围和菜单的一样,begin和end中间是多个加速键的定义项目,每个键占据一行,各字段的含义如下所示。

键名:加速对应的按键,可以有3种方式定义:

"^字母":表示加上字母键。

"字母":表示字母,这时类型必须指明是VIRTKEY。

数值:表示ASCII码为该数值的字母,这时类型必须指明位ASCII。

命令ID:按下加速键后,windows发送的命令ID。

类型:加速键定义的方式,可以是VIRTKEY和ASCII,表示“键名”字段定义的是虚拟键还是ASCII码。

选项:可以是Alt,Control或Shift中的单个或多个。

如F1,F2,BackSpace和Esc等都是用虚拟键的方法定义的,他们以VK带头的一些值:如VK_BACK,VK_TAB,VK_ESCAPE,VK_DELETE,VK_F1,VK_F2等。不同类型资源ID可以是相同的。

3、使用菜单和加速键

1、加载菜单

加载菜单的方法有两个,一是在注册窗口类的时候指定类的默认菜单;二是在建立窗口的时候在参数中指定菜单句柄。

invoke CreateWindowEx,WS_EX_CLIENTEDGE,\

offset szClassName,offset szCaptionMain,\

WS_OVERLAPPEDWINDOW,\

100,100,400,300,\

NULL,hMenu,hInstance,NULL

首先必须用LoadMenu函数来获取菜单句柄hMunu,如下:

Invoke LoadMenu,hInstance,IDM_MAIN

Mov hMenu,eax

第一个参数是用GetModuleHandle获取实例句柄,第二个参数是参数资源ID。

2、加载加速键

invoke LoadAccelerators,hInstance,IDA_MAIN

; 消息循环

;********************************************************************

.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

TranslateAccelerator是实现加速键功能的核心,参数为目标窗口、加速键句柄和消息结构。遇到WM_KEYDOWN和WM_SYSKEYDOWN消息就检查加速键资源,是否符合某个加速键,符合就发送WM_COMMAND或WM_SYSCOMMAND消息。并返回TRUE,否则返回FALSE。符合加速键的键盘消息不应再发送给窗口,TranslateMessage和DispatchMessage函数前的逻辑判断就是这样的意图:只有TranslateAccelerator没有转换的消息(eax为0)才继续。

3、菜单和加速键消息

WM_COMMAND消息的两参数:

wParam的高位=wNotifyCode;通知码

wParam的低位=wID;命令ID

lParam=hwndCtl;发送WM_COMMAND的子窗口句柄

对于菜单和加速键引发的WM_COMMAND的消息,lParam的值为零,菜单的通知码为0,加速键的通知码为1。

.elseif eax == WM_COMMAND

mov eax,wParam

movzx eax,ax

.if eax==命令ID1

.elseif eax==命令ID2

....

.elseif

4、菜单的修改

AppendMenu添加菜单项

InsertMenu插入菜单项

ModifyMenu修改菜单项

DeleteMenu删除菜单项

RemoveMenu删除菜单项

DeleteMenu和RemoveMenu的区别在于当popup菜单时,删除所有的菜单。

5、使用系统菜单

选择系统菜单windows发送WM_SYSCOMMAND消息。默认有还原、大小、最大化、最小化、关闭等,资源ID已经预定义:SC_RESTORE,SC_MOVE,SC_SIZE,SC_MAXIMIZE,SC_MINIMIZE和SC_CLOSE等。读者可以自己处理WM_SYSCOMMAND消息,但一般不需要自己处理的,而是交给DefWindowProc处理。

在系统菜单中添加菜单项

;********************************************************************

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

GetSystemMenu获取系统菜单。

处理系统菜单消息

;********************************************************************

.elseif eax == WM_SYSCOMMAND

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

6、右键弹出菜单

利用TrackPopupMenu函数实现的,

Invoke TrackPopuMenu,hMenu,uFlags,x,y,nReserved,hWnd,lpRect

x,y位置弹出hWnd窗口(发送WM_COMMAND消息到这个窗口)的菜单,窗口句柄hMenu。注意坐标是以整个屏幕为准的。uFlags菜单的位置,PM_CENTERALIGN(中间),TPM_LEFTALIGN(右上角),TPM_RIGHTALIGN(右下角)。准备工作,处理右键事件才弹出菜单WM_RBUTTONDOWN消息中调用TrackPopupMenu函数。

首先要获取鼠标位置,GetCursorPos。注意的是,菜单类型句柄一定是弹出popup类型的。LpadMenu函数载入第一层非popup类型菜单,GetSubMenu得到第二层弹出菜单。

7、菜单状态的检查和设置

对菜单状态的检查可以用GetMenuState函数来完成,

Invoke GetMenuState,hMenu,uId,uFlags

当uFlags是MF_BYCOMMAND的时候,uId当命令ID指定菜单项,当uFlags是MF_BYPOSITION的时候uId当索引,失败返回-1。

EnableMenuItem禁用、可用、灰色、菜单

CheckMenuItem打钩选中

CheckMenuRadioItem单项选择

当用户在菜单按动鼠标的时候,windows在菜单弹出之前会向窗口过程发送WM_INITMENU消息。

8、其他菜单函数

动态创建菜单,首先CreateMenu建立一个空项菜单并返回句柄,AppendMenu添加菜单项。

CreatePopupMenu建立一个空弹出菜单并返回popup类型的菜单句柄,可以再TrackPopupMenu中直接使用。

GetMenu函数获取一个窗口当前使用的菜单句柄。GetMenuItemCount函数获取一个菜单的总项数,返回值不包括子菜单展开以后的项数,而是最上层的菜单项数。GetSubMenu可以一层层地统计下去。

GetMenuString和GetMenuItemID查询菜单的字符串和ID。

SetMenu设置不同的菜单句柄,与窗口相连的菜单句柄在窗口摧毁的时候由windows自动释放,没连接的否则用DestroyMenu函数释放(如没有与窗口相连的TrackPopupMenu弹出菜单)。

 

二、图标和光标

1、图标和光标的资源定义

图标ID ICON [DISCARDABLE] 图标文件名 ;定义图标

光标ID CURSOR [DISCARDABLE] 光标文件名 ;定义光标

DISCARDABLE表示不用的时候可以再内存中卸载

MyIcon icon "1.ico"

1000 icon  discardable 2.ico

1001 ico "big icon.ico"

1002 cursor "big arrow.ani"

GoodCursor cursor arrow.cur

2、使用图标光标

1、载入图标和光标

载入图标

Invike LoadIcon,hInstance,lpIconName

.if eax

  Mov hIcon,eax

.endif

载入光标

LoadCursor和LoadCursorFromFile。具体参数参考MASN。

2、使用图标和光标

Invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,hIcon

消息wParam参数可以是ICON_BIG或ICON_SMALL指定图标的分辨率。

如果要改变窗口的光标,正确的办法是用SetClassLong函数改变窗口的属性,可以永久改变类中的光标设定。

Invoke SetClassLong,hWnd,nIndex,dwNewLong

这个函数可以改变一个窗口类几乎所有属性。

 

三、位图

色彩表和位图数据和在一起叫做设备无关位图(DIB)。IDB是位图数据的超集。

Windows支持位图的格式有bmp、ioc、cur等几种。GDI操作中只有bmp文件。其他格式使用必须转换到位图才能使用。

位图ID BITMAP [DISCARDABLE] 位图文件名

LoadBitmap函数载入,DeleteObject函数释放资源。