一、Windows的图标、光标、字符串和自订资源—取得图示句柄
如果您仔细阅读ICONDEMO.RC和RESOURCE.H文件,会看到由Developer Studio产生用于维护文件的一些标记。然而,当编译资源描述档时,只有少数几行是重要的。这些从ICONDEMO.RC和RESOURCE.H文件中摘录下来的关键部分被列在程序10-2中。
ICONDEMO.RC (摘录) //Microsoft Developer Studio generated resource script. #include "resource.h" #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// // Icon IDI_ICON ICON DISCARDABLE "icondemo.ico"
RESOURCE.H (摘录) // Microsoft Developer Studio generated include file. // Used by IconDemo.rc #define IDI_ICON 101
程序10-2 ICONDEMO.RC和RESOURCE.H文件的摘录 |
程序10-2所显示的ICONDEMO.RC和RESOURCE.H文件与您在普通的文字编辑器中手动建立的很相似,80年代的Windows程序写作者就是这样做的。唯一不同的是AFXRES.H,它是个表头文件,包含了在建立由机器产生的MFC项目时由Developer Studio使用的常用标识符。在本书中,我们不会用到AFXRES.H。
ICONDEMO.RC中的这行
IDI_ICON ICON DISCARDABLE "icondemo.ico"
是资源描述档的ICON叙述。该图示有一个数值标识符IDI_ICON,等于101。由Developer Studio添加的DISCARDABLE关键词指出,必要时Windows可以从内存中丢弃图标,以获得额外的空间。之后不需要程序任何特定的操作,Windows就能够重新加载图示。DISCARDABLE属性是内定的,不需要指定。只有在名称和目录路径包含空格时,Developer Studio才将文件名加上引号。
当资源编译程序将编译的资源储存在ICONDEMO.RES中,并且由连结程序将资源添加到ICONDEMO.EXE中以后,该资源就可以经由一个资源型态(RT_ICON)和一个标识符(IDI_ICON或101)来标识。程序可以通过呼叫LoadIcon函数取得此图示的句柄:
hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON)) ;
请注意ICONDEMO在两个地方呼叫这个函数,一次在定义窗口类别时,另一次在窗口消息处理程序中取得图标的句柄用于绘制。LoadIcon传回HICON型态的值,它是图示的句柄。
LoadIcon的第一个参数,是指出资源来自哪个文件的执行实体句柄。使用hInstance表示它来自程序自己的.EXE文件。LoadIcon的第二个参数实际上被定义为指向字符串的指针。待会将会看到,可以使用字符串而不是用数值标识符标识资源。宏MAKEINTRESOURCE(把整数转换成资源字符串)生成指向非数字的指针,如下所示:
#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
LoadIcon知道,如果第二个参数的高字组为0,那么低字组就为图示的数值标识符。图标的标识符必须为16位值。
本书前面的范例程序使用了预先定义的图示:
LoadIcon (NULL, IDI_APPLICATION) ;
hInstance参数被设定为NULL,因此Windows知道这是预先定义的图示。IDI_APPLICATION也在WINUSER.H中用MAKEINTRESOURCE定义:
#define IDI_APPLICATION MAKEINTRESOURCE(32512)
LoadIcon的第二个参数带来了一个有趣的问题:图标的标识符能可以为字符串吗?答案是可以。方法如下:在 Developer Studio中,在ICONDEMO项目的文件列表上,选择 IDONDEMO.RC。您会看到顶端为「IconDemo Resource」的树状结构,然后是资源型态「Icon」,再下来是「IDI_ICON」。如果用鼠标右键单击图标标识符,并从菜单上选择「 Properties」,您就能改变ID。实际上,您可以把名称放在引号内将其更改为字符串。我用这种方法指定资源名称,并在本书的其它地方也使用该方法。
我喜欢为图示(以及一些其它资源)使用文字名称,因为名称可以是程序的名称。例如,假定文件被命名为MYPROG。如果您使用「Icon Properties」对话框将图标的ID指定为「MyProg」(包括引号),资源描述档将包含下列叙述:
MYPROG ICON DISCARDABLE myprog.ico
然而,在RESOURCE.H中并没有#define叙述,来指出MYPROG是数值标识符。资源描述文件将假定MYPROG是字符串标识符。
在C程序中,使用LoadIcon函数来取得图示句柄。您可能已经有了表示程序名的字符串:
static TCHAR szAppName [] = TEXT ("MyProg") ;
这意味着程序可以使用叙述:
hIcon = LoadIcon (hInstance, szAppName) ;
来加载图标,这比宏MAKEINTRESOURCE更清晰一些。
但是如果您确实想用数字来命名,那么您可以用数字代替标识符或字符串。在「Icon Properties」对话框中,在ID栏中输入数字。资源描述档将有一个类似下面的ICON叙述:
125 ICON DISCARDABLE myprog.ico
可以使用两种方法之一引用图示。明显易读的方式是:
hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (125)) ;
另一个不易阅读的方式是:
hIcon = LoadIcon (hInstance, TEXT ("#125")) ;
Windows识别初始字符#作为ASCII形式中字符数值的开头。