分享
 
 
 

送给初学者的礼物:游戏编程起源连载三

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

第二章 使用Win32程序资源

一、简介

欢迎继续收看!通过本章题目可能你已经猜出了本章论题,我将教会你在Windows程序中使用资源。简单的讲,资源即数据,它们通常是和程序的EXE文件相关联的,但是它们又是独一无二的。首先,资源在运行过程中不能被修改。它们实际上都是只读文件,而且程序代码不能够直接访问它们。另外,资源并不在程序的数据区内。在装入时,程序资源通常在某个磁盘文件中,直到程序需要它们时才被装入。使用资源是一件很容易的事情,并且它的妙处无穷。Windows为我们提供了大量的资源类型,但我们这里只学一些最常用,最容易的:图标(icon)、光标(cursor)、位图(bitmap)、菜单(menu)和字符串(string)。此后,我还将教你建立自己风格类型的资源,使你为所欲为。

重复一下,要想看懂本章,你得有点C语言的基础。C++有时用一用,但不影响你学习本章内容。并且我假定你已经读过了上一章内容“Windows编程基础”。还是用Microsoft Visual C++的编译器。

资源脚本

在进行细节之前,我们要先搞懂怎样要编译器知道它所要编译的资源类型。方法是使用称之为资源脚本的特殊文件,它是一个简单的文本文件,可以手工编辑,也可以让Visual C++自动编辑,或者你用其它的自动编辑器编辑。无论如何,资源脚本文件要有一个.rc的扩展名。大多数的脚本文件都从定义资源行开始,最简单的资源行通常要用到资源类型,就像这样:

[identifier]

[resource type]

[filename]

【标识符】

【资源类型】

【文件名称】

标识符可以用两种方式表示:一种是能表示资源意思的字符串,另一种是在资源相对应的头文件中用#define定义过的数字常量。如果你选择数字常量,这通常是一个好主意,别忘了把相应的头文件加入到你的资源脚本。资源脚本使用C语言风格的文件格式好像比较容易理解。以下是一个比较简单的资源脚本实例:

#include "resource.h"

// icons

ICON_MAIN ICON myicon.ico

// bitmaps

IMG_TILESET1 BITMAP tileset.bmp

IMG_TILESET2 BITMAP tileset2.bmp

例子中的ICON_MAIN和IMG_TILESET是字符串呢,还是数字常量?这无伤大雅,编译器编译的时候会自己判断。如果发现在头文件中有#define的定义,那就认为是字符常量,否则,就是字符串。如果有些迷茫,不要紧。我将解释我们要用到的每一个资源类型。如果您觉得麻烦那让我们用全自动的资源插入系统吧!(在Visual C++中,在“插入”下拉菜单中,选择“资源”)现在你知道了建立资源脚本的基础知识,让我们开始进一步的行程吧!

图标和光标

你每天在使用的大多数的Windows程序,都有自己的图标,简单的说,就是EXE文件同这个图标资源相关联了,独特风格的光标也是如此。你已经知道图标的脚本行样子了,光标的和它很相似,看看吧:

[identifier] CURSOR [filename]

[identifier] ICON [filename]

增加了一行脚本行后,也就是意味着你的EXE文件又多了一个关联。也就是说你的EXE文件要根据标识符去相应的位置寻找相应的文件[filename]。你可以使用任何你喜欢用的图标/光标编辑器去编辑相应的文件。我通常利用Visual C++中的编辑器。

把资源脚本做出来后,并没有完事儿,因为你还不知道怎么调用相应的资源,要想知道图标和光标是怎样在你的程序中被调用的,让我们回过头来,看一看上一章中的窗口类(windows class)文件:

WNDCLASSEX sampleClass; // declare structure variable

sampleClass.cbSize = sizeof(WNDCLASSEX);

// always use this!

sampleClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;

// standard settings

sampleClass.lpfnWndProc = MsgHandler;

// message handler function

sampleClass.cbClsExtra = 0;

// extra class info, not used

sampleClass.cbWndExtra = 0;

// extra window info, not used

sampleClass.hInstance = hinstance;

// parameter passed to WinMain()

sampleClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);

// Windows logo

sampleClass.hCursor = LoadCursor(NULL, IDC_ARROW);

// standard cursor

sampleClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

// a simple black brush

sampleClass.lpszMenuName = NULL;

// no menu

sampleClass.lpszClassName = "Sample Class"

// class name

sampleClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

// Windows logo again

还记得它吧?这个hIcon用来表示整个程序;hIconSm用来出现在开始菜单和窗口的标题栏里;hCursor用来表示在你所创建的窗口中的光标的样子。我向你保证,我们要实现自己的风格一点都不复杂。下面是它们的原形:

HICON LoadIcon(

HINSTANCE hInstance,

// handle to application instance

LPCTSTR lpIconName

// icon-name string or icon resource identifier

);

HCURSOR LoadCursor(

HINSTANCE hInstance,

// handle to application instance

LPCTSTR lpCursorName

// name string or cursor resource identifier

);

返回的类型是它们自己相对应的类型。其内部的参数都很直观:

※ HINSTANCE hInstane:但程序执行时,把图标或光标相对应的句柄传递给WinMain()函数。若要使用Windows的标注图标或光标,就把它设置为NULL。

※ LPCTSTR lpIconName,lpCursorName:是你要调用的资源的标识符字符串。如果你在脚本文件中用字符串直接作为标识符,就直接传送它好了;如果你是用数字常量,就要使用一个Windows头文件里的宏MAKEINTRESOURCE()来把它们协调一致。

让我们看一看下面的资源脚本,是关于图标和光标的:

#include "resource.h"

ICON_MAIN ICON myicon.ico

CURSOR_ARROW CURSOR arrow.cur

如果标识符ICON_MAIN合CURSOR_ARROW在头文件resource.h中没有被#define定义过,那么我们将直接传递它给资源调用函数,象这样:

sampleClass.hIcon = LoadIcon(hinstance, "ICON_MAIN");

如果它们在头文件resource.h中这样定义过:

#define ICON_MAIN 1000

#define CURSOR_ARROW 2000

你就必须用宏MAKEINTRESOURCE()把它们转变为LPCTSTR类型。下面给出你几种意义相同的调用方法,都是正确的喔!

sampleClass.hIcon = LoadIcon(hinstance,

MAKEINTRESOURCE(ICON_MAIN));

or...

sampleClass.hIcon = LoadIcon(hinstance,

MAKEINTRESOURCE(1000));

or...

int ident = 1000;

sampleClass.hIcon = LoadIcon(hinstance,

MAKEINTRESOURCE(ident));

关于图标和光标的调用,你学的差不多了。就这个话题,我还想告诉你一件事儿。如果你除了在程序的开始设置光标外,在程序中还要设置光标,有一个简单的Windows函数可以完成它:

HCURSOR SetCursor(HCURSOR hCursor);

仅仅一个参数,它是一个句柄,是在调用LoadCursor()时得到的,函数返回调用的上一个光标的句柄,如果没有设置过上一个光标,返回值是NULL。

位图

想要往程序里添加图象,通过位图资源可能是最简单的办法了。位图是Windows之本,当然提供了一些函数来处理位图,请记住,如果你使用了太多的位图,你的EXE文件将要非常巨大。在资源脚本中设置位图同图标和光标没什么区别:

[identifier] BITMAP [filename]

有一个函数LoadBitmap(),同LoadCursor()和LoadIcon()的用法很相似,它将得到一个句柄,由于我还没有讲过图形(graphics),就不具体说函数的功能了,你可以猜一猜它是怎样工作的,一旦你得到了图形句柄,你将怎样使用它呢?更多的留待以后再讲。不要担心,现在只是要你有点儿准备。下面看看我们还应该学点儿什么。

字符串表格

字符串表

字符串表是我最喜欢的资源类型。正象你所想的:一个充满字符串的庞大表格。字符串表有很多用处。你可以用它存储你的文件名称,游戏中的人物对话,消息框中的文本,菜单中的文本等等。在资源脚本里建立一个字符串表很容易,就像这样:

STRINGTABLE

{

// entries go here

}

一个字符串表由几部分组成:一个标识字符串的数字;紧跟着一个逗号;然后是加了双引号的字符串本身。字符串表里的字符串被允许使用溢出符号,如

或 。注意,字符串表本身并没有标识符,所以每个程序只能有一个字符串表。一个简单的字符串表可能象下面这个样子:

// program information

STRINGTABLE

{

1, "3D Space Game v1.0"

2, "Written by The Masked Coder"

3, "(C) 2000 WienerDog Software"

}

从程序的字符串表里调用字符串,将使用――你可能猜到了――LoadString()函数。这是它的原形:

int LoadString(

HINSTANCE hInstance, // handle to module containing string resource

UINT uID,

// resource identifier

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有