显示区域的大小
如果您使用过现有的Windows应用程序,可能会发现窗口的尺寸变化极大。窗口最大化时(假定窗口只有标题列并且没有菜单),显示区域几乎占据了整个屏幕。这一最大化了的显示区域的尺寸可以通过以SM_CXFULLSCREEN和SM_CYFULLSCREEN为参数呼叫GetSystemMetrics来获得。窗口的最小尺寸可以很小,有时甚至不存在,更不用说显示区域了。
在最近一章,我们使用GetClientRect函数来取得显示区域的大小。使用这个函数没有什么不好,但是在您每次要使用信息时就去呼叫它一遍是没有效率的。确定窗口显示区域大小的更好方法是在窗口消息处理程序中处理WM_SIZE消息。在窗口大小改变时,Windows给窗口消息处理程序发送一个WM_SIZE消息。传给窗口消息处理程序的lParam参数的低字组中包含显示区域的宽度,高字组中包含显示区域的高度。要保存这些尺寸,需要在窗口消息处理程序中定义两个静态变量:
static int cxClient, cyClient ;
与cxChar和cyChar相似,这两个变量在窗口消息处理程序内定义为静态变量,因为在以后处理其它消息时会用到它们。处理WM_SIZE的方法如下:
caseWM_SIZE: cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; return 0 ;
实际上您会在每个Windows程序中看到类似的程序代码。LOWORD和HIWORD宏在Windows表头文件WINDEF.H中定义。这些宏的定义看起来像这样:
#define LOWORD(l) ((WORD)(l)) #define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
这两个宏传回WORD值(16位的无正负号整数,范围从0到0xFFFF)。一般,将这些值保存在32位有号整数中。这就不会牵扯到任何转换问题,并使得这些值在以后需要的任何计算中易于使用。
在许多Windows程序中,WM_SIZE消息必然跟着一个WM_PAINT消息。为什么呢?因为在我们定义窗口类别时指定窗口类别样式为:
CS_HREDRAW | CS_VREDRAW
这种窗口类别样式告诉Windows,如果水平或者垂直大小发生改变, 则强制更新显示区域。
用如下公式计算可以在显示区域内显示的文字的总行数:
cyClient / cyChar
如果显示区域的高度太小以至无法显示一个完整的字符,这个公式的结果可以为0。类似地,在显示区域的水平方向可以显示的小写字符的近似数目为:
cxClient / cxChar
如果在处理WM_CREATE消息处理期间取得cxChar和cyChar,则不用担心在这两个计算公式中会出现被0除的情况。在WinMain呼叫CreateWindow时,窗口消息处理程序接收一个WM_CREATE消息。在WinMain呼叫ShowWindow之后接收到第一个WM_CREATE消息,此时cxChar和cyChar已经被赋予正的非零值了。
如果显示区域的大小不足以容纳所有的内容,那么,知道窗口显示区域的大小只是为使用者提供了在显示区域内卷动文字的第一步。如果您对其他有类似需求的Windows应用程序很熟悉,就很可能知道,这种情况下,我们需要使用「滚动条」。