您所在的位置:读书频道 > 设计开发 > 其它开发 > 2.1.2 理解MyRegisterClass

2.1.2 理解MyRegisterClass

2011-03-02 18:50 陈征/傅鑫 等译 机械工业出版社 字号:T | T
一键收藏,随时查看,分享好友!

《游戏编程入门(原书第3版)》第2章侦听Windows消息,本章将更详细地学习Windows消息机制和主循环,并编写一个完整的能够在屏幕上显示一些内容的窗口程序。将学习窗口句柄和设备环境如何一起在窗口上产生输出。本章继续探究实时游戏循环,尤其是获得WinMain之外的实时循环的方法。我们将在本章学到一些新的技巧,以便让实时循环运行,为下一章的DirectX做准备。本节为大家介绍MyRegisterClass。

AD:

2.1.2 理解MyRegisterClass

MyRegisterClass是一个非常简单的函数,它用于设置程序所需的主窗口类的值。MyRegisterClass中的代码本可放置在WinMain中。实际上,所有这些东西本来都可以塞到WinMain里面,Windows是不会抱怨的。不过,把Windows程序的初始化代码分开放置到可识别的(也是标准的)助手函数中可以使程序更易理解一些,至少在学习阶段是如此。WinMain调用InitInstance并且通过调用MyRegisterClass来设置程序窗口。这又是一个并非必需的可选助手函数(既然必须将代码插到某个地方,何不直接用这个函数呢?)。也可以重命名这个函数,Windows不会介意。

1. MyRegisterClass函数调用

InitInstance将两个参数传递给MyRegisterClass,以便设置窗口类:

 

我们对这些参数都已熟悉了。hInstance就是那个由WinMain传递给InitInstance的实例。这个变量到处可见!读者还记得吧,hInstance储存运行中的程序的当前实例, InitInstance会将它的值复制到一个全局变量中。第二个参数很容易理解,它是InitInstance中以char *类型创建的值,且被初始化为窗口类名称(本例中为“Hello World”)。注意,这也可以是个Unicode字符串。

建议 MyRegisterClass返回的ATOM数据类型被定义为WORD,而WORD在Windows的一个头文件中被定义为unsigned short。为什么不直接使用unsigned short呢?笔者还真不知道。如果你想这么做当然可以!笔者敢打赌Microsoft里甚至都没人记得这个ATOM是怎么来的。

2. MyRegisterClass的要点

这个函数的要点是什么?下面再次列出MyRegisterClass()以便参考。在代码清单之后将详细讲解这个函数。这些属性的使用对于Windows程序来说简直就像家务活。笔者对此不太关心的原因是当DirectX登场之后我们将占有窗口。所以,有谁会去关心这个注定很快会被硬件polygon所占领的窗口要用哪个特殊属性呢?不过,在初期讲解所有这些基础知识很重要。笔者从大师Charles Petzold那里学习了《Windows编程》,而现在,通过间接的方式,该轮到你向他学习了!

 

首先,MyRegisterClass定义了一个新变量wc,类型是WNDCLASS。这个结构的每个成员都按顺序在MyRegisterClass中定义了,所以没必要列出这个结构。

窗口样式wc.style被设置成CS_HREDRAW | CS_VREDRAW。管道符号(|)代表一种位合并的方法。CS_HREDRAW值使得程序窗口在移动或尺寸调整改变宽度时完全重新绘制。同样的,CS_VREDRAW使得窗口高度调整后完全重新绘制。

wc.lpfnWinProc变量需要多做一些解释,因为它不是一个简单的变量,而是一个指向一个回调函数的长指针。这是非常重要的,要是不设定这个值,消息就无法传递给程序窗口(hWnd)。当Windows消息和这个hWnd的值匹配时,回调窗口过程会自动被调用。所有的消息都是如此,包括用户输入和窗口重绘。任何按钮的按下、屏幕的刷新或其他事件的发生都会经历这一回调过程。这个函数可以起任意名称,例如BigBadGameWindowProc,只要它的返回值是LRESULT CALLBACK而且参数正确即可。

结构变量wc.cbClsExtra和wc.cbWndExtra在大多数时候应设为零。这些变量只用来为窗口过程多增加一些额外的内存空间,我们实在是无需使用它们。

wc.hInstance设为传递给MyRegisterClass的hInstance参数值。主窗口需要知道正在使用的是哪个实例。如果真想让程序晕菜,不妨将每个新实例设置为指向同一个程序窗口。这会很有趣!不过这应该不可能发生,因为游戏的新实例会被终止,不允许运行。

wc.hIcon和wc.hCursor可以很好地自解释。LoadIcon函数通常用于从资源中装载一个图标图像,而MAKEINTRESOURCE宏为资源标识符返回一个字符串值。这个宏在游戏中不常使用(除非游戏需要在窗口中运行)。

wc.hbrBackground被设置为用于绘制程序窗口背景的一个刷子句柄。默认使用的是后援对象WHITE_BRUSH。它可以是一个位图图像、一个自定义刷子或者任何一种颜色。

wc.lpszMenuName被设置为程序菜单的名称,这也是一个资源。本书中的示例程序不使用菜单。

wc.lpszClassName被设置为传递给MyRegisterClass的szWindowClass参数值。它给窗口指定特定的类名称,和hWnd一起用在消息处理中。

最后,MyRegisterClass调用RegsiterClassEx函数。设置了窗口细节的WNDCLASS变量wc传递给了这个函数。如果返回值为零表示失败;如果成功地将窗口注册到了Windows,那么这个值将传回给InitInstance。

唉,这些是否搅得你头疼?这里不指望读者现在就能够记住所有这些信息,不过作为游戏程序员,理解所有的工作原理总是不错的,这样能最大地发挥出所使用的硬件的能力。

建议 InitInstance和MyRegsiterClass函数中的代码并不是一定要位于不同的函数中。可以将这些代码直接放在WinMain中,我们在后面的章节中就是这么做的。但目前,分成多个小步骤来实现有助于理解Windows编程。

【责任编辑:云霞 TEL:(010)68476606】

回书目   上一节   下一节

×
分享到:

  1. Linux服务器配置全程实录
  2. 揭秘--优秀PPT这样制作

热点职位

更多>>

热点专题

更多>>

读书

Ubuntu Linux入门到精通
本书全面介绍了Ubuntu Linux的相关知识,内容详实,论述清晰。主要内容包括Ubuntu介绍、文件系统管理、进程管理、压缩与查询

51CTO旗下网站

领先的IT技术网站 51CTO 领先的中文存储媒体 WatchStor 中国首个CIO网站 CIOage 中国首家数字医疗网站 HC3i