天天看点

windows编程之资源的编译和使用

1windows资源

资源就是数据,Windows程序除了程序代码外,还应该存储更多的额资源,这样包含代码和数据的exe。Windows中的资源在exe中的存储如下所示:

windows编程之资源的编译和使用

2 资源的编译

         有一个叫做资源编译器(ResourceCompiler)的程序,它接受一个扩展名为.RC的ASCII文本资源文件作为输入。该文件是一个C/English类似结构的文件-描述了编译到单个数据文件中的所有资源。之后该资源编译器装载所有的资源,并将所有资源放置在一个具有.RES扩展名的大数据文件中。

         这个.RES文件包含了你在.RC文件中定义的诸如图标、光标、位图、声音等所有资源的二进制数据。该.RES文件和.CPP、.H、.LIB、.OBJ等等文件一样都可以编译成一个.EXE文件。可以向程序中添加许多数据类型和对象,然后它们以资源的形式和实际程序代码一起驻留在.EXE文件中(一般在文件的尾端)。在运行过程中,可以访问这个资源数据库,并且可以从程序本身(而不是作为一个单独的文件从磁盘中)装载资源数据。要创建该资源文件,必须有一个以ASCII文本形式的资源描述文件,名称为*.RC。然后将该文件传递到编译器中(一起访问该资源),并且产生一个*.RES文件。然后将该.RES文件和所有的其他程序对象连接到一起,创建一个最终的.EXE文件。资源的编译过程如下图所示:

windows编程之资源的编译和使用

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) 资源视图的文件树状结构

windows编程之资源的编译和使用

从中我们可以清楚的看到那些是资源ID是字符串,哪些资源ID是数字,我们可以任意点击一个,然后打开其属性编辑框,如下所示:

windows编程之资源的编译和使用

我们修改其ID,改为”MyCursor”,这样在程序中也可以做到修改数字ID为字符串ID的结果,但是不用去通过修改代码来实现。

4 String 资源的使用:

         使用string作为资源主要是考虑不同语言之间的翻译问题。使用过程如下所示:

windows编程之资源的编译和使用

然后在标题列输入字符串的值,不要包含引号

windows编程之资源的编译和使用

然后在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);
           

关于自订资源,菜单栏,对话框的放在以后讲解。