1windows资源
资源就是数据,Windows程序除了程序代码外,还应该存储更多的额资源,这样包含代码和数据的exe。Windows中的资源在exe中的存储如下所示:
2 资源的编译
有一个叫做资源编译器(ResourceCompiler)的程序,它接受一个扩展名为.RC的ASCII文本资源文件作为输入。该文件是一个C/English类似结构的文件-描述了编译到单个数据文件中的所有资源。之后该资源编译器装载所有的资源,并将所有资源放置在一个具有.RES扩展名的大数据文件中。
这个.RES文件包含了你在.RC文件中定义的诸如图标、光标、位图、声音等所有资源的二进制数据。该.RES文件和.CPP、.H、.LIB、.OBJ等等文件一样都可以编译成一个.EXE文件。可以向程序中添加许多数据类型和对象,然后它们以资源的形式和实际程序代码一起驻留在.EXE文件中(一般在文件的尾端)。在运行过程中,可以访问这个资源数据库,并且可以从程序本身(而不是作为一个单独的文件从磁盘中)装载资源数据。要创建该资源文件,必须有一个以ASCII文本形式的资源描述文件,名称为*.RC。然后将该文件传递到编译器中(一起访问该资源),并且产生一个*.RES文件。然后将该.RES文件和所有的其他程序对象连接到一起,创建一个最终的.EXE文件。资源的编译过程如下图所示:
3 资源的使用
.RC文件包含所有资源的定义,也就是说在程序中可以使用多个资源。Windows可以使用ASCII文本字符串或者是整数标识符来表示资源。在大多数情况下,你可以在.RC文件中同时使用这两种方式,但是应当注意一些资源只允许使用其中的一种。无论是哪种情况,资源必须以稍微不同的方式来加载,并且如果涉及到标识符的话,在你的工程中必须包含一个额外的包含符号交叉引用的.H文件。
(1)resource.h,xxx.rc文件内容窥探
可以看到xxx.rc中有include “resource.h”。现在我们字定义一个光标,一个图标,分别看看两个文件的内容。
//{{NO_DEPENDENCIES}} //Microsoft Visual C++ generated include file. // Usedby Win32Temp.rc // #define IDI_ICON1 101 #define IDC_CURSOR1 102 // Nextdefault values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 104 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
然后再看看xxx.rc文件中主要部分:
///////////////////////////////////////////////////////////////////////////// // // Icon // // Iconwith lowest ID value placed first to ensure application icon //remains consistent on all systems. IDI_ICON1 ICON "icon1.ico" ///////////////////////////////////////////////////////////////////////////// // //Cursor // IDC_CURSOR1 CURSOR "cursor1.cur" #endif // 中D文?(简¨°体¬?,ê?中D国¨²) resources
根据之前介绍的加载资源是从rc(资源描述文档),rc文件定义了所有的资源,所以resource.h中的那些宏定义只是为了方便找到资源ID然后进行加载而已,如:
wndclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
此时就要在包含头文件 resource.h,因为要用到IDI_ICON1.
(2)资源标示符可以是字符串
我们新建一个光标资源,然后在resource.h 中注释掉这一行
//#defineIDC_CURSOR2 103
此时在程序中,我们这样改写:
wndclass.hCursor = LoadCursor(hInstance,TEXT("IDC_CURSOR2") );程序运行结果和
wndclass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));
的结果一致,说明了资源标示符可以为字符串。
前提:当没有resource.h或者resource.h中没有 XX_ID的定义的时候,XX_ID会被当做字符串来被处理。
(3)资源标示符是字符串的另一种用法
//resource.h #define IDR_MENU1 xxx //xxx.rc ///////////////////////////////////////////////////////////////////////////// // // Menu // IDR_MENU MENU // winMain.cpp HMENU hMenu = LoadMenu(hInstance,TEXT("xxx"));
(4)总结
针对 IDC_CURSOR3 CURSOR "cur00001.cur"
wndclass.hCursor = LoadCursor(hInstance,TEXT("cur00001.cur") ); //错误用法,不能把文件名当做资源标识符 wndclass.hCursor = LoadCursor(hInstance,TEXT("IDC_CURSOR3") ); // IDC_CURSOR3没定义时是正确的 wndclass.hCursor =LoadCursor(hInstance,MAKEINTRESOURCE("IDC_CURSOR3") ); //IDC_CURSOR3 被宏定义时是正确的
(5) 资源视图的文件树状结构
从中我们可以清楚的看到那些是资源ID是字符串,哪些资源ID是数字,我们可以任意点击一个,然后打开其属性编辑框,如下所示:
我们修改其ID,改为”MyCursor”,这样在程序中也可以做到修改数字ID为字符串ID的结果,但是不用去通过修改代码来实现。
4 String 资源的使用:
使用string作为资源主要是考虑不同语言之间的翻译问题。使用过程如下所示:
然后在标题列输入字符串的值,不要包含引号
然后在resource.h和XX.rc中可以看到多出来的东西
#define IDS_STRING106 106 #define IDS_STRING107 107
xx.rc中如下:
STRINGTABLE BEGIN IDS_STRING106 "Thanksgiving" IDS_STRING107 "Festival" END
程序中调用如下所示:
TCHAR szFormat[40]; LoadString((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),IDS_STRING106,szFormat,40);
关于自订资源,菜单栏,对话框的放在以后讲解。