11.2.1 WinMain()函数(3)
在Windows知道我们需要的窗口特性以及为该窗口处理消息的函数是什么之后,即可创建该窗口。用于完成该操作的函数是CreateWindow()。我们已经创建的窗口类确定了应用程序窗口的一般特性,而传递给CreateWindow()函数的其他实参将添加一些附加的特性。因为应用程序通常可以有多个窗口,所以CreateWindow()函数将返回所创建窗口的句柄。可以存储该句柄,以便稍后能够引用这个特定的窗口。有许多API调用都要求指定窗口句柄作为参数。此刻,可以看一看CreateWindow()函数的典型用法。代码如下:
- HWND hWnd; // Window handle
- ...
- hWnd = CreateWindow(
- szAppName, // the window class name
- "A Basic Window the Hard Way", // The window title
- WS_OVERLAPPEDWINDOW, // Window style as overlapped
- CW_USEDEFAULT, // Default screen position of upper left
- CW_USEDEFAULT, // corner of our window as x,y...
- CW_USEDEFAULT, // Default window size, width...
- CW_USEDEFAULT, // ...and height
- 0, // No parent window
- 0, // No menu
- hInstance, // Program Instance handle
- 0 // No window creation data
- );
HWND类型的变量hWnd是指向某个窗口的32位整数句柄,或者在64位模式中则为64位整数句柄。我们将使用该变量来记录CreateWindow()函数返回的窗口句柄。给该函数传递的第一个实参是类名称。Windows使用该参数来识别前面在RegisterClassEx()函数调用中传递的WNDCLASSEX struct,这样来自该struct的信息就能用于窗口的创建过程。
CreateWindow()函数的第二个实参定义标题栏上出现的文本。第三个实参指定该窗口在创建之后应具有的样式。这里指定的选项WS_OVERLAPPEDWINDOW实际上组合了多个选项。该选项将窗口定义为具有WS_OVERLAPPED、WS_CAPTION、WS_SYSMENU、WS_THICKFRAME、WS_MINIMIZEBOX和WS_MAXIMIZEBOX样式。结果是一个计划用作主应用程序窗口的可重叠窗口,该窗口包括标题栏和粗框架,标题栏上有标题栏图标、系统菜单、最大化按钮和最小化按钮。对于拥有粗框架的窗口,可以调整其边框的大小。
接下来4个实参确定了该窗口在屏幕上的位置和大小。前两个是窗口左上角的屏幕坐标,后两个定义了窗口的宽度和高度。CW_USEDEFAULT值表示希望Windows为该窗口分配默认的位置和大小,它告诉Windows沿屏幕向下在层叠位置排列连续的窗口。CW_USEDEFAULT仅应用于被指定为WS_OVERLAPPED的窗口。
下一个实参值是NULL,表明创建的窗口不是子窗口(依赖父窗口的窗口)。如果希望该窗口是子窗口,则应当将该实参设置为父窗口的句柄。再下来一个实参也是NULL,它表明不需要菜单。之后,指定由Windows传递给程序的当前程序实例的句柄。最后一个表示窗口创建数据的实参是NULL,因为在本示例中只需要一个简单的窗口。如果需要创建一个多文档界面(multiple-document interface,MDI)客户窗口,则最后一个实参应当指向某个与此相关的结构。稍后我们将学习与MDI窗口有关的更多内容。
Windows API还包括一个 CreateWindowEx()函数,可用来以扩展的样式信息创建窗口。
在调用CreateWindow()函数之后,被创建的窗口现在已经存在,但还没有显示在屏幕上。需要调用另一个Windows API函数将该窗口显示出来:
- ShowWindow(hWnd, nCmdShow); // Display the window
这里只需要两个实参。第一个实参标识要显示的窗口,它是CreateWindow()函数返回的句柄。第二个实参是给WinMain()传递的nCmdShow值,它指出在屏幕上显示窗口的方式。
3. 初始化程序窗口
在调用ShowWindow()函数之后,该窗口将出现在屏幕上,但仍然没有应用程序的内容,因此需要使程序在该窗口的工作区中输出信息。可以直接在WinMain()函数中将某些输出代码放在一起,但这种方法是最不令人满意的:在这种情况下,操作系统认为工作区的内容不是永久性的。如果希望保留工作区的内容,则不能仅输出所需内容,然后将其忘之脑后。用户修改窗口的任何动作(如拖动边框或整个窗口),通常都需要重画窗口及工作区。
当因任何原因而需要重画工作区时,Windows将给程序发送一条特定的消息,而WindowProc()函数需要以重构窗口的工作区作为响应。因此,最初绘制工作区的最好方法是把绘制工作区的代码放入WindowProc()函数,并使Windows给程序发送请求重画工作区的消息。当我们在程序中知道应该重画窗口(如修改某些内容的时候)时,需要告诉Windows发送一条窗口应该重画的消息。
通过调用另一个Windows API函数UpdateWindow(),请求Windows给程序发送一条重画窗口工作区的消息。该函数调用的语句如下:
- UpdateWindow(hWnd); // Cause window client area to be drawn