2.2.1 Win32 SDK风格的框架(3)
有了上面的一些准备以后,下面我们就要开始创建窗口了。首先需要传递CreateWindowEx()所需的所有参数,如扩展风格、类名字(与你在注册窗口类时所用的名字相同)、窗口标题、窗体风格、窗体的左上角坐标(0,0 是个安全的选择)、窗体的宽和高,我们创建的窗口没有父窗口,也不需要菜单,这些参数被设为NULL。值得注意的是在窗体风格中包括了 WS_CLIPSIBLINGS 和 WS_CLIPCHILDREN两个属性,为了保证OpenGL程序正常运行,这两个属性是必需的,因为它们阻止别的窗体在我们的窗体内部或上面绘图。细心的读者可能发现我们还检测了一下窗口是否正常创建,如果成功则hWnd保存窗口的句柄,如果失败,弹出消息窗口,并退出程序。
下面第224~244行的代码描述像素格式,像素格式是用来定义OpenGL绘图属性的,由于OpenGL和Windows在像素格式方面不一定一致,因此需要在这两个系统里面进行协商和匹配,于是需要设置一个叫做PIXELFORMATDESCRIPTOR的结构体来传递OpenGL和Windows之间一些系统功能信息,进而完成协商和匹配。在这里我们选择了通过RGBA(红、绿、蓝、alpha通道)支持OpenGL和双缓存的格式,我们试图找到匹配我们选定的色彩深度(16位、24位、32位)的像素格式,最后设置16位Z-缓存,其余的参数要么未使用要么不重要(stencil buffer模板缓存和accumulation buffer累加缓存除外)。
如果前面创建窗口时没有错误发生,我们接着尝试取得OpenGL设备上下文。若无法取得设备上下文,弹出错误消息,然后程序退出(返回FALSE);若成功获得设备描述表,则第253行尝试找到对应与此前我们选定的像素格式的像素格式。如果Windows不能找到,弹出错误消息,并退出程序(返回FALSE)。当Windows找到匹配的像素格式后,将尝试设置像素格式,如果无法设置,弹出错误消息,并退出程序(返回FALSE)。
在这里有必要再次说明一下Windows设备上下文(Device Context,DC)和OpenGL渲染上下文(Rendering Context,RC)之间的关系。具有Windows编程(www.cppentry.com)经验的人都知道Windows下用GDI作图必须通过设备上下文调用相应的函数来实现,同样OpenGL绘图是通过渲染上下文来实现的,其中RC必须只能通过已经建立的DC来创建。但绘制时需要将RC和一个DC关联起来,这样我们就可以使用OpenGL所提供的函数命令将图形通过当前RC对应的DC来绘制到相应的显示设备上。具体到我们的程序中,通过第267行的wglCreateContext()函数从显示设备上创建一个OpenGL的渲染上下文hRC,当创建成功后,第274行调用wglMakeCurrent()函数把生成的渲染上下文hRC跟显示设备上下文hDC关联起来,如果成功我们以后就可以使用OpenGL命令绘制所需要的图形了。
至此,OpenGL窗口已经创建完成,下面的任务就是把它显示出来。在这里我们将它设为前端窗口(给它更高的优先级),并将焦点移至此窗口,然后调用ReSizeGLScene函数设置OpenGL显示屏幕的宽度和高度。在第286行程序跳转至 InitGL(),这里可以设置光照、纹理等任何需要设置的东西。你可以在 InitGL()内部自行定义错误检查,并返回 TRUE (一切正常)或FALSE (有什么不对),例如,如果你在InitGL()内装载纹理并出现错误,你可能希望程序停止,如果你返回 FALSE,下面的代码会弹出错误消息,并退出程序。最后第293行完全确定创建窗口已经成功了,向WinMain()返回TRUE,告知WinMain()没有错误,以防止程序退出。