11.2.2 消息处理函数(2)
不能杂乱无章地在窗口中涂鸦。在可以向应用程序窗口写入内容之前,需要告诉Windows我们想这样做,还需要得到Windows的授权才能继续。为此,调用Windows API函数BeginPaint(),只应该在响应WM_PAINT消息时才调用该函数,使用方法如下:
- HDC hDC; // A display context handle
- PAINTSTRUCT PaintSt; // Structure defining area to be redrawn
- hDC = BeginPaint(hWnd, &PaintSt); // Prepare to draw in the window
HDC类型表示显示设备上下文的句柄,更通常的叫法是设备上下文。设备上下文在与设备无关的Windows API函数(向屏幕或打印机输出信息)和设备驱动程序(支持向连接到PC的具体设备输出信息)之间提供链接。也可以把设备上下文看作Windows应我们的请求传递给我们的权限标记,它授予我们输出某种信息的权限。如果没有设备上下文,就不能生成任何输出。
BeginPaint()函数返回设备上下文的句柄,该函数要求提供两个实参。传递的第一个实参hWnd是窗口句柄,用来标识输出的目标窗口。第二个实参是PAINTSTRUCT变量PaintSt的地址,Windows把为了响应WM_PAINT消息而需要重画的区域的相关信息放在PaintSt结构内。本书将不讨论该结构的细节,因为我们不打算再次使用它。此处将只是重画整个工作区。使用下面这条语句,可以在RECT结构中获得工作区的坐标:
- RECT aRect; // A working rectangle
- GetClientRect(hWnd, &aRect);
GetClientRect()函数为第一个实参指定的窗口提供其工作区的左上角和右下角坐标。这两个坐标存储在第二个指针实参传递的RECT结构aRect中。使用aRect可以标识工作区中的一个区域,DrawText()函数在这个区域中输出文本。因为窗口是灰色的背景,所以应该将文本的背景色更改为透明,以便让灰色显露出来;否则,文本将在白色背景上出现。可以用下面的API函数调用来做这件事:
- SetBkMode(hDC, TRANSPARENT); // Set text background mode
第一个实参标识设备上下文,第二个实参设定背景模式。默认选项是OPAQUE。
现在可以使用下面这条语句来输出文本:
- DrawText(hDC, // Device context handle
- L"But, soft! What light through yonder window breaks ",
- -1, // Indicate null terminated string
- & aRect, // Rectangle in which text is to be drawn
- DT_SINGLELINE| // Text format - single line
- DT_CENTER| // - centered in the line
- DT_VCENTER // - line centered in aRect
- );
DrawText()函数的第一个实参是允许在窗口上绘图的权限证书,显示设备上下文hDC。第二个实参是希望输出的文本字符串。也可以将该文本字符串定义在某个变量中,然后传递指向该文本字符串的指针作为该函数调用的第二个实参。下一个值为-1的实参表示该字符串是以空字符终止的。如果不是这样,就应当将字符串中字符的个数写在这里。第4个实参是指向某个RECT结构的指针,该结构定义了一个希望在其中输出文本的矩形。在本例中,该矩形是aRect中定义的整个窗口工作区。最后一个实参定义了矩形中文本的格式。在这里使用按位或运算符 | 组合3个格式说明常量。该字符串写在一行内,文本在这一行上居中显示,在垂直方向上,该文本行位于矩形的中心。这样的格式处理可以将文本美观地放在窗口中心。还有许多其他选项,其中包括将文本放在矩形的顶部或底部,以及使文本左对齐或右对齐的选项。
在输出所有希望显示的内容之后,必须告诉Windows工作区的绘制已经结束。对每个BeginPaint()函数调用来说,都必须有一个对应的EndPaint()函数调用。因此,为了结束对WM_PAINT消息的处理,需要下面这条语句:
- EndPaint(hWnd, &PaintSt); // Terminate window redraw operation
hWnd实参标识程序窗口,第二个实参是由BeginPaint()函数填充的PAINTSTRUCT结构的地址。