WIN32汇编语言教程:第05章 使用资源 · 5.2 图标和光标(1)
图标和光标是图形资源,图标通常用做应用程序的“形象代表”出现在文件浏览器、运行窗口左上角或程序的快捷方式等所有代表文件的地方,为自己写的应用程序选一个合适的图标会使程序变得引人注目;而光标就是鼠标移动时屏幕上那个指示位置的东西,应用程序可以定义自己的光标,这样光标移到程序的客户区中就会变成需要的形状。
5.2.1 图标和光标的资源定义
和菜单、加速键等资源不同,在资源脚本文件中定义图标和光标时并不是一个个像素地定义,而是指定图标和光标的文件名,由资源编译器将像素数据读入再转换成二进制格式,所以在资源定义之前要用其他工具先创建图标和光标文件。图标和静态光标文件的扩展名分别是ico和cur,还有一种扩展名为ani的动态光标文件。
光标和图标在资源文件中的定义语句是:
图标ID ICON [DISCARDABLE] 图标文件名 ;定义图标
光标ID CURSOR [DISCARDABLE] 光标文件名 ;定义光标
DISCARDABLE关键字是内存选项,表示在不用的时候可以从内存暂时卸掉,当文件名包含空格时,两边要用双引号引起来,图标ID和光标ID同样也可以用16位的整数或字符串表示,这里是几个定义的例子:
MyIcon icon “1.ico” ;把1.ico定义为ID为“MyIcon”的图标资源 1000 icon discardable 2.ico ;把2.ico定义为ID为1000的图标资源 1001 icon “big icon.ico” ;把big icon.ico定义为ID为1001的图标资源 1002 cursor “big arrow.ani” ;把big arrow.ani定义为ID为1002的光标资源 GoodCursor cursor arrow.cur ;把arrow.cur定义为ID为“GoodCursor”的光标资源
资源文件中定义的图标可以不止一个,但Windows在“我的电脑”中列出文件的时候总是使用资源中的第一个图标当做文件的图标,所以在资源脚本文件中要把想用做程序图标的图标定义语句排在最前面。
5.2.2 使用图标和光标
在这里,用一个例子来说明图标和光标的用法,程序是建立在FirstWindow.asm和Menu.asm程序的基础上的,为了节省篇幅,在这里就不列出全部源程序了,完整的源程序可以在所附光盘的Chapter05\Icon目录中找到。程序中创建了一个菜单,运行后可以在“图标和光标”菜单中选择不同的图标和光标,选择不同的图标以后,窗口标题栏左边的图标和桌面任务栏上的窗口图标都会变化;选择不同的光标后,当鼠标移动到窗口客户区中的时候,光标会变成程序指定的光标。具体的效果如图5.3所示,大图标对应“笑脸”,小图标对应“箭头”,而光标A和B分别是“小恐龙”光标和“手型”光标,其中“小恐龙”光标是ani类型的动态光标,在屏幕上显示为一个走动中的恐龙模样。
图5.3 不同的图标和光标
资源文件Icon.rc的定义如下:
//################################################################## #include <resource.h> //################################################################## #define ICO_BIG Ox1000 #define ICO_SMALL Ox1001 #define CUR_2 Ox1000 #define IDM_MAIN Ox2000 #define IDM_EXIT Ox2101 #define IDM_BIG Ox2201 #define IDM_SMALL Ox2202 #define IDM_CUR1 Ox2203 #define IDM_CUR2 Ox2204 //################################################################## ICO_SMALL ICON "Small.ico" ICO_BIG ICON "Big.ico" CUR_2 CURSOR "2.cur" //################################################################## IDM_MAIN menu discardable BEGIN popup "文件(&F)" BEGIN menuitem "退出(&X)", IDM_EXIT END popup "图标和光标(&I)" BEGIN menuitem "大图标(&G)", IDM_BIG menuitem "小图标(&M)", IDM_SMALL menuitem separator menuitem "光标A(&A)", IDM_CUR1 menuitem "光标B(&B)", IDM_CUR2 END END //##################################################################
经过上一节的“洗礼”,读者对菜单的定义应该很熟悉了,这里就不再说明IDM_MAIN的定义了,脚本文件中定义了ICO_SMALL,ICO_BIG两套图标和CUR_2静态光标,磁盘上还有个动态光标文件1.ani。
Icon.asm的大部分是窗口模板程序的内容,和FirstWindow.asm是相同的,仅在窗口过程的WM_CREATE和WM_COMMAND增加了一些内容:
.const szCursorFile db '1.ani',0 .code ... .if eax == WM_CREATE invoke LoadIcon,hInstance,ICO_BIG mov hIcoBig,eax invoke LoadIcon,hInstance,ICO_SMALL mov hIcoSmall,eax invoke LoadCursorFromFile,addr szCursorFile mov hCur1,eax invoke LoadCursor,hInstance,CUR_2 mov hCur2,eax invoke SendMessage,hWnd,WM_COMMAND,IDM_BIG,NULL invoke SendMessage,hWnd,WM_COMMAND,IDM_CUR1,NULL .elseif eax == WM_COMMAND mov eax,wParam movzx eax,ax .if eax == IDM_EXIT call _Quit .elseif eax == IDM_BIG invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,hIcoBig invoke CheckMenuRadioItem,hMenu,\ IDM_BIG,IDM_SMALL,IDM_BIG,MF_BYCOMMAND .elseif eax == IDM_SMALL invoke SendMessage,hWnd,\ WM_SETICON,ICON_BIG,hIcoSmall invoke CheckMenuRadioItem,hMenu,\ IDM_BIG,IDM_SMALL,IDM_SMALL,MF_BYCOMMAND .elseif eax == IDM_CUR1 invoke SetClassLong,hWnd,GCL_HCURSOR,hCur1 invoke CheckMenuRadioItem,hMenu,\ IDM_CUR1,IDM_CUR2,IDM_CUR1,MF_BYCOMMAND .elseif eax == IDM_CUR2 invoke SetClassLong,hWnd,GCL_HCURSOR,hCur2 invoke CheckMenuRadioItem,hMenu,\ IDM_CUR1,IDM_CUR2,IDM_CUR2,MF_BYCOMMAND .endif