中国领先的IT技术网站
|
|

2.1.2 理解MyRegisterClass

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

作者:陈征/傅鑫 等译来源:机械工业出版社|2011-03-02 18:50


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】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢
24H热文
一周话题
本月最赞

读 书 +更多

非常网管——网络工程案例

本书面向企业网络应用需求,详细介绍了Windows网络互联解决方案、中小企业共享上网解决方案、基于ISA Server 2006的代理服务器与防火墙解决...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊
× 学习达标赢Beats耳机