兰陵月 发表于 2018-3-23 14:04:30

琢石成器WIN32汇编程序设计学习(九)-第5章 使用资源(三)

5.2 图标和光标资源
图标和光标是图形资源,图标通常用作应用程序的“形象代表”出现在文件浏览器、运行窗口左上角或程序的快捷方式等所有代表文件的地方,为自己写的应用程序选一个合适的图标会使应用程序变得引入注目;而光标就是鼠标移动时屏幕上那个指示位置的箭头,应用程序可以定义自己的光标,这样,光标移动到程序的客户区中就会变成需要的形状。
5.2.1 图标和光标的资源定义
与菜单、加速键等资源不同,在资源代码文件中定义图标和光标时并不是一个一个像素的定义,而是指定图标和光标的文件名,由资源编译器将像素数据读入再转换成二进制格式。由此可见,在资源定义之前要用其他工具先创建图标和光标文件。图标和静态光标文件的扩展名分别是ico和cur,还有一种扩展名为ani的动态光标文件。
光标和图标在资源文件中的定义语句是:
图标IDicon 图标文件名;定义图标
光标IDcursor 光标文件名;定义光标
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 使用图标和光标
对Icon例程的解析。
资源文件分析:
第4行~第12行,分别定义了无参数的宏,全部定义为常量。第14行~第16行,定义图标和光标资源,第14行,把small.ico定义为ID为ICO_SMALL(即0x1001)的图标资源;第15行,把Big.ico定义为ID为ICO_BIG(即0x1000)的图标资源;第16行,把2.cur定义为ID为CUR_2(即0x1000,不同类型的资源可以使用相同的ID,Windows能够自动进行区别)的光标资源。
第18行~第32行,定义了菜单资源。第18行,定义了ID为IDM_MAIN(即0x2000)的菜单;第19行~第32行,定义菜单项。第20行~第23行,定义了菜单文字为“文件(F)”弹出式菜单,第22行,定义了该菜单下一个菜单文字为“退出(X)”的菜单项,其命令ID为IDM_EXIT(即0x2101);第24行~第31行,定义了菜单文字为“图标和光标(I)”的弹出式菜单,第26行~第30行,定义了该菜单下5个菜单项,分别是菜单文字为“大图标(G)”的菜单项(命令ID为IDM_BIG,即0x2201)、菜单文字为“小图标(M)”的菜单项(命令ID为IDM_SMALL,即0x2202)、菜单项分割线、菜单文字为“光标A(A)”的菜单项(命令ID为IDM_CUR1,即0x2203)、菜单文字为“光标B(B)”的菜单项(命令ID为IDM_CUR2,即0x2204)。
ASM源文件解析:
程序入口点在第158行,直接调用_WinMain函数。该函数的具体过程与前面一样,不再重复。稍有不同的是在窗口消息处理函数里面,主要是其中的两个消息进行分别处理,这两个消息分别是WM_CREATE消息和WM_COMMAND消息。
第70行~第80行,第71行调用LoadIcon函数加载图标句柄,该函数有两个参数,第一个参数hInstance,表示要包含要加载图标的模块实例的句柄,此处当前运行的程序句柄;第二个参数lpIconName,表示指向要加载的图标资源文件名的字符串指针,也可以是高16位为0的整数(即图标资源ID值),此处为ICO_BIG。整句指令表示加载ID值为ICO_BIG的图标资源。第72行,将该图标资源句柄给hIcoBig。第73、74行,加载ID为ICO_SMALL的图标资源,并将其句柄给hIconSmall。
第75行,调用LoadCursorFromFile函数加载文件中的动态光标资源,该函数有一个参数lpFileName,表示用于创建光标的源文件数据。文件中的数据必须为. cur或. ani格式。同时,如果lpFileName的高字是非零的,那么它就是指向一个字符串的指针,该字符串是该光标数据的文件的全名。本例程中为指向文件名字符串的指针addr szCursorFile。函数返回值是新光标的句柄值,第76行,将新加载的光标的句柄值给hCur1。
第77、78行,调用LoadCursor函数加载资源ID值为0x1000的光标资源。该函数通LoadIcon函数差不多,也有两个参数。第一个参数hInstance,表示要加载的光标所在的可执行文件的模块实例的句柄(如果加载的是windows自带的光标,那么第一个参数必须为空)。本例程中为主程序的句柄;第二个参数为lpCursorName,表示指向以NULL结束的字符串的指针,该字符串存有等待载入的光标资源名。 同时也可以光标的资源ID值。本例程中使用的是光标资源的ID值(ID值为0x1000)。
图标一般使用在对话框中或者程序窗口的标题栏中,要在标题栏中设置图标可以用向窗口发送WM_SETICON消息的办法实现:
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,hIcon
该函数的原型是:SendMessagehWnd,wMsg,wParam,lParam,它有四个参数,第一个参数hWnd,指示接收消息的窗口的句柄,本例程中为hInstance,也就是主程序窗口的句柄;第二个参数是wMsg,指示被发送的消息,本例程中其值为WM_COMMAND,第三个参数wParam指示命令ID的值,第四个参数值为NULL(即0)。注意SendMessage函数调用后必须等待消息处理后才结束,因此运行第79行,由于属于同一个线程,所以SendMessage函数会自动再次调用窗口过程处理,此时直接到了第87行,第88行,再次调用SendMessage函数,此函数又调用窗口处理过程。直到处理完成后,逐层返回到第79行。第80条,再次调用该函数发送一个WM_COMMAND消息,运行过程同上一条。
这是一个设置窗口图标的消息,这个消息有两个附加参数(需要在函数调用时一并填写的),分别是wParam和lParam,wParam参数指示要设置的图标类型,它的值可以是ICO_BIG或者ICO_SMALL,用来指示图标的分辨率是32×32还是16×16。lParam参数指示图标的句柄。
要将窗口的光标设置为新的光标不能使用WM_SETCURSOR,这个消息是通知窗口重新刷新光标而不是让它设定指定的光标。Windows中有个SetCursor函数可以用来设置窗口光标,但这只能将新的光标维持很短一段时间,因为当Windows向窗口重新发送WM_SETCURSOR消息的时候,光标就会设置成原来的样子,而不妙的是,Windows常常会自动向窗口过程发送WM_SETCURSOR消息,所以SetCursor并不能用来永久地改变光标。
如果要改变窗口的光标,正确的办法是用SetClassLong函数改变窗口类的属性,具体用法见资料。
页: [1]
查看完整版本: 琢石成器WIN32汇编程序设计学习(九)-第5章 使用资源(三)