2.2.1 Win32 SDK风格的框架(2)
接下来该开始创建OpenGL窗口。在开始之前,我们可以考虑这样一个问题,如果我们将要创建一个固定的全屏模式窗口,这将不需要许多额外的代码,也许这样比较简单。但是如果我们想要创建一个不使用全屏幕的窗口,那该怎么办?还有怎样在程序中改变窗口的标题栏?怎样改变窗口的分辨率或pixel format(像素格式) 为了解决这一系列问题,我们决定创建一个容易定制的友好的窗口,虽然它需要更多的代码。以下的代码完成了所有这一切!
正如第130行所示,此过程返回布尔变量(TRUE 或 FALSE)。它还带有5个参数:窗口的标题栏、窗口的宽度、窗口的高度、色彩位数(16/24/32),和全屏标志(TRUE——全屏模式, FALSE——窗口模式 )。返回的布尔值告诉我们窗口是否成功创建。
当我们要求Windows寻找相匹配的像素格式时,Windows寻找结束后将模式值保存在变量PixelFormat中。第133行定义的wc用来保存窗口类的结构,窗口类结构中保存着窗口信息,通过改变类的不同字段可以改变窗口的外观和行为,每个窗口都属于一个窗口类,当你创建窗口时,你必须为窗口注册类。接下来两行的变量dwExStyle和dwStyle存放扩展和通常的窗口风格信息,使用变量来存放风格的目的是为了能够根据需要创建的窗口类型(是全屏幕下的弹出窗口还是窗口模式下的带边框的普通窗口)来改变窗口的风格。
下面的5行代码取得矩形的左上角和右下角的坐标值,我们将使用这些值来调整窗口使得其上的绘图区的大小恰好是所需的分辨率的值。通常如果我们创建一个640×480的窗口,窗口的边框会占掉一些分辨率的值。在第142行我们让全局变量fullscreen等于fullscreenflag。如果我们希望在全屏幕下运行而将fullscreenflag设为TRUE,但没有让变量fullscreen等于fullscreenflag,fullscreen变量将保持为FALSE,当我们在全屏幕模式下销毁窗口的时候,变量fullscreen的值却不是正确的TRUE值,计算机将误以为已经处于桌面模式而无法切换回桌面。总之,fullscreen的值必须永远等于fullscreenflag的值,否则就会有问题。
在下面的代码中,我们取得窗口的实例,然后定义窗口类。
第144行取得窗口实例句柄。
第145行中的CS_HREDRAW 和 CS_VREDRAW 的含义是,无论何时,只要窗口发生变化时就分别从水平方向和垂直方向强制重画。CS_OWNDC为窗口创建一个私有的DC,这意味着DC不能在程序间共享。
第146行中的WndProc是我们程序的消息处理过程。
第147~148行中,由于没有使用额外的窗口数据,这两个字段都设为零。
第149行设置程序实例句柄。
第150行表示采用Windows系统的默认窗口图标。
第151行表示采用Windows系统的默认的标准鼠标箭头。
第152行表示窗口的背景色采用Windows系统的默认设置。
第153行表示不添加窗口菜单。
第154行设定上面所定义的窗口类的名字,它可以定义为你想要的任何名字,出于简单,我们记为OpenG。
现在注册类名字,如果有错误发生,弹出错误消息窗口。按下OK按钮后程序退出。
第162行查看程序应该在全屏模式还是窗口模式下运行,如果应该是全屏模式,我们将尝试设置全屏模式。在切换到全屏模式时,有几件十分重要的事必须牢记:必须确保在全屏模式下所用的宽度和高度等同于窗口模式下的宽度和高度,最最重要的是要在创建窗口之前设置全屏模式,在这里的代码中,你无须再担心宽度和高度,它们已被设置成与显示模式所对应的大小。
第165和166行定义和分配了用于存储屏幕设置结构体的内存空间。接下来几行设定了屏幕的宽、高和色彩深度,即在dmScreenSettings中保存了所有的宽、高和色彩深度信息。
第173行使用ChangeDisplaySettings来尝试切换成与dmScreenSettings所匹配模式,我们使用参数CDS_FULLSCREEN来切换显示模式,因为这样做不仅移去了屏幕底部的状态条,而且它在来回切换时,没有移动或改变你在桌面上的窗口。如果模式未能设置成功,不能匹配全屏模式,则弹出消息窗口,提供两个选项:在窗口模式下运行或退出。如果用户选择窗口模式,变量fullscreen 的值变为FALSE,程序继续运行;如果用户选择退出,弹出消息窗口告知用户程序将结束,并返回FALSE告诉程序窗口未能成功创建,程序退出。
程序继续往下运行,由于全屏模式可能失败,用户可能决定在窗口下运行,我们需要在设置屏幕/窗口之前,再次检查fullscreen的值是TRUE或FALSE。如果我们仍处于全屏模式,设置扩展窗体风格为WS_EX_APPWINDOW,这将强制窗体可见时处于最前面;再将窗体的风格设为WS_POPUP,这个类型的窗体没有边框,使我们的全屏模式得以完美显示。最后我们禁用鼠标指针,当你的程序不是交互式的时候,在全屏模式下禁用鼠标指针通常是个好主意。如果我们使用窗口而不是全屏模式,我们在扩展窗体风格中增加了 WS_EX_WINDOWEDGE,增强窗体的3D感观,窗体风格改用 WS_OVERLAPPEDWINDOW,则创建一个带标题栏、可变大小的边框、菜单和最大化/最小化按钮的窗体。第202行根据创建的窗体类型调整窗口,调整的目的是使得窗口大小正好等于我们要求的分辨率。通常情况下边框会占用窗口的一部分,使用AdjustWindowRectEx 后,我们的OpenGL场景就不会被边框盖住,实际上窗口变得更大以便绘制边框,注意在全屏模式下此命令就不起什么作用了。