210 likes | 408 Views
( 第十八讲 ). 吉林大学远程教育课件. Windows A P I 编 程. ( 第十八讲 ). 学 时: 48. 主讲人 : 翟慧杰. 本实例的作用是通过程序捕获键盘消息, 然后将 wParam 参数所包含的数据进行分解, 最后将各项信息通过窗口显示出来。实例 的源文件包含了 Initlnstance 、 MyRegisterClass 、 ShowKey 、 WinMain 和 WndProc 五个函数。程序的基本思路
E N D
(第十八讲) 吉林大学远程教育课件 Windows A P I编 程 (第十八讲) 学 时:48 主讲人 : 翟慧杰
本实例的作用是通过程序捕获键盘消息, 然后将wParam参数所包含的数据进行分解, 最后将各项信息通过窗口显示出来。实例 的源文件包含了Initlnstance、 MyRegisterClass、ShowKey、WinMain 和WndProc五个函数。程序的基本思路 是以WinMain函数作为程序入口,再调用 MyRegisterClass函数和 InitInstance函数注册窗口类并创建和保存窗日,然后创建和显示窗口,最后进入消息循环。 下面重点分析函数WndProc和ShowKey。
1.WndProc函数 在本实例中WndProc函数处理的消息 主要有WM_CREATE、WM_SIZE、 WM_PAINT和键盘消息。 case WM_CREATE://处理窗口创建的消息 hdc = GetDC (hwnd); //设定字体 SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)); //检取当前字体的度量数据 GetTextMetrics (hdc, &tm); xChar = tm.tmAveCharWidth;//保存字体平均宽度 yChar = tm.tmHeight;//保存字体高度 ReleaseDC (hwnd, hdc); rc.top = 3 * yChar / 2; return 0;
这一程序段的主要作用是将字体对象选入 当前窗体的设备描述表中,同时取得字体 高度和平均宽度,再初始化编辑区的滚屏 区域的右上角Y坐标。进入该程序段后, 首先通过GetDC函数获得当前窗体的 设备描述表,再通过GetStockObject函数 获得系统字体,然后用 SelectObject函数 将字体对家选入窗体的设备描述表中。其中,hdc为设备描述表句柄。在完成所有操作后,程序还必须通过ReleaseDC函数释放设备描述表。在该程序段中使用了GetTextMetrics函数来获得字体的几何尺寸。GetTextMetrics函效的原型定义如下: BOOL GetTextMetrics( HDC hdc, // 指向设备描述表的句柄 LPTEXTMETRIC lptm // TEXTMETRIC结构体变量的指针 // 所获得的所有信息保存在TEXTMETRIC结构体变量中 ));
其中lptm是一个指向 TEXTMETRIC 结构体的指针。 TEXTMETRIC结构体 包含了与字体的几何尺寸相关的基本信息。 该结构体的具体定义如下: typedef struct tagTEXTMETRIC{ // tm LONG tmHeight;// 字体高度 LONG tmAscent;//字体高于基准线的高度 LONG tmDescent;// 字体低于基准线的高度 LONG tmInternalLeading;// 给大写字母留出的空间 LONG tmExtenalLeading; // 由字体设计者推荐的附加行距 LONG tmAveCharWidth;// 字体平均宽度 LONG tmMaxCharWidth;// 字体最大宽度 LONG tmWeight; // 字体黑度 LONG tmOverhang; // 在合成斜体或黑体时加在字符上的附加宽度值 LONG tmDigitizedAspectX;// 字体所适合的高宽比的宽 LONG tmDigitizedAspectY; // 字体所适合的高宽比的高
BCHAR tmFirstChar; // 字体中定义的第一个字符 BCHAR tmLastChar; //字体中定义的最后一个字符 BCHAR trnDefaultChar; //字体中的默认字符 BCHAR trnBreakChar; // windows在调整文本时用于分裂词的字符 BYTE tmItalic; // 取非零值时表示斜体字体 BYTE tmUnderLined; // 取非零值时表示下划线字体 BYTE tmStruckOut;// 取非零值时为删除线字体 BYTE tmPitchAndFamily; // 低二位为字符间距,高四位为系列值 BYTE tmCharSet; // 指定字符集 }TEXTMETRIC; 该结构中所有的字体大小都是按逻辑单位给出的,这就是说字体的大小取决于当前显示设备的映射模式。
在例中,所获得的字体几何尺寸保存在 TEXTMETRIC结构体变量tm中。滚屏区域 的范围是通过RECT结构体变量re保存的, RECT结构体变量可以通过记录矩形区域 的右上角和左下角的坐标来确定一个矩形 区域。RECT结构的原型定义如下: typedef struc RECT{ LONG left; // 矩形左上角 X坐标 LONG top; // 左上角 Y坐标 LONG right; // 右下角 X坐标 LONG bottom; // 右下角Y坐标 } RECT; 该结构定义了一个矩形区域的左上角和右下角的坐标。由结构的原型定义我们可以知道该结构包括四个域,其中left域表示矩形的左上角X坐标,top域表示左上角Y坐标,right域表示右下角X坐标,bottom域表示右下角Y坐标。通常用于一个矩形区域范围的记录和传递。
例如,通过RECT结构的变量将一个矩形 区域范围的四个角的值传递FillRect函数, 则调用该函数后,矩形区域除了最下方的 一行和最右方一列外都被填充。 在本实例中,初始化编辑区的滚屏区域的 左上角Y坐标时,使用了如下程序: rc . top=3 * yChar/2; 这是因为在窗口中首先要输出两行的题头信息,一行为中文,一行为下划线。中文字符的高度为1个字体高度单位,而下划线的高度为半个字体高度单位。这两行信息是一直保持,不参与滚屏的。因此,滚屏区域的左上角Y坐标从3/2个字体高度处开始。
在WndProc函数中,处理WM_ SIZE 消息的程序段如下: case WM_SIZE: //处理窗口大小改变的消息 //窗体改变后保存新的滚屏区域右下角坐标 rc.right = LOWORD (lParam); rc.bottom = HIWORD (lParam); UpdateWindow (hwnd); return 0; 该程序段比较简单,只是当窗口的尺寸改变时重新设定滚屏区域的右下角坐标,并更新窗口。值得注意的是, WM_SIZE消息的wParam变量保存了窗体新尺寸的左上角坐标,变量的32位分为两个部分,低16位保存X坐标,高16位保存Y坐标。 lParam变量保存了窗体新尺寸的右下角坐标,保存方式与wParam变量相同。在编程过程中,通常通过LOWORD宏定义来获得32位变量的低16位数值,通过HIWORD宏定义来获得32位变量的高历位数值。
该程序段比较简单,只是当窗口的尺寸改变 时重新设定滚屏区域的右下角坐标,并更新 窗口。值得注意的是, WM_SIZE消息的 wParam变量保存了窗体新尺寸的左上角坐标, 变量的32位分为两个部分,低16位保存X坐标, 高16位保存Y坐标。 lParam变量保存了窗体新 尺寸的右下角坐标,保存方式与wParam变量 相同。在编程过程中,通常通过LOWORD宏定义来获得32位变量的低16位数值,通过HIWORD宏定义来获得32位变量的高历位数值。
WndProc函数中,处理WM _PAINT 消息的程序段如下: case WM_PAINT: //处理窗口重绘消息 InvalidateRect (hwnd, NULL, TRUE); hdc = BeginPaint (hwnd, &ps); SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, xChar, yChar / 2, szTop, (sizeof szTop) - 1) ; TextOut (hdc, xChar, yChar / 2, szUnd, (sizeof szUnd) - 1) ; EndPaint (hwnd, &ps); return 0; 该程序段首先调用InvalidateRect函数使窗口无效,InvalidateRect函数的功能是使窗口的某一部分无效,也就是通知Windows该部分需要被刷新和重画。 在InvalidateRect函数之后,程序调用函数BeginPaint准备重画窗口。
BeginPaint函数的原型定义如下: HDC BeginPaint( HWND hwnd , //重画窗口的句柄 LPPAINTSTRUCT lpPaint // 指向一个用于保存所有重 // 画信息的PAINTSTRUCT结构体变量的指针 ); BeginPaint函数的作用是完成重画窗体之前的准备,并将重画窗体的数据保存在一个PAINTSTRUCT结构体变量中。PAINTSTRUCT结构体可以用于保存窗口重画时的数据以方便以后使用。
PAINTSTRUCT结构体的定义如下: typedef struct tagPAINTSTRUCT{ // ps HDC hdc; // 重画区域所在窗口的句柄 BOOL fErase;// 是否擦去背景 RECT rcPaint; // 指定重画窗体的范围 BOOL fRestore; // 系统保留域 BOOL fIncUpdate;// 系统保留域 BYTE rgbReserved[32];// 系统保留 )PA INTSTRU CT;
BeginPaint函数如果操作成功会返回一个 被操作窗口的设备描述表的句柄。如果操作 不成功则函数返回NULL值,表明显示设备 不可用。该函数在运行过程中,会进行自动 调整,使得所有区域都包含在刷新区域的范围 内。而原有需要刷新的区域是由 InvalidateRect函数或 InvalidateRgn函数指定的。一般来说,只有当程序处理 WM_PAINT消息时才调用BeginPaint函数,而且,每次调用BeginPaint函数都需要对应调用一个EndPaint函数来结束重画过程。在BeginPaint函数调用后,会将插入符光标自动隐藏。EndPaint函数原型定义如下: BOOL EndPaint ( HWND hWnd, // 窗口句柄 CONST PAINTSTRUCT* lpPaint // 指向 PAINTSTRUCT结构体变量的指针 );
EndPaint函数标志着窗口重画过程的结束。 该函数执行后总返回一个非零值。如果在 BeginPaint函数执行时将插入符号隐藏了, 那么EndPaint函数会重新显示插入符号。 消息处理函数WndProc处理的键盘消息有: WM_ KEYDOWN、WM_KEYUP WM_CHAR、 WM_DEADCHAR、WM_SYSKEYDOWN、 WM_SYSKEYUP、WM_SYSCHAR和WM_SYSDEADCHAR。根据不同的消息,程序会用不同的参数调用ShowKey函数在窗口中显示各键盘消息的相关信息。
2.ShowKey函数 ShowKey函数是用户自定义函数,其 作用是从键盘消息的各域中提取信息 并显示在窗口中。 ShowKey函数的具体定义如下: // 作用:实现在窗口中显示按键信息 void ShowKey (HWND hwnd, int iType, char *szMessage,WPARAM wParam, LPARAM lParam) { static char *szFormat[2] = { "%-14s %3d %c %6u %4d %5s %5s %6s %6s", "%-14s %3d %c %6u %4d %5s %5s %6s %6s" } ; char szBuffer[80]; HDC hdc;
SelectObject(hdc, GetStockObject (SYSTEM_FIXED_FONT)); TextOut (hdc, xChar, rc.bottom - yChar, szBuffer,wsprintf (szBuffer, szFormat [iType], szMessage, //消息 wParam, //虚拟键代码 (BYTE) (iType ? wParam : ' '),//显示字符值 LOWORD (lParam), //重复次数 HIWORD (lParam) & 0xFF, //OEM键盘扫描码 //判断是否为增强键盘的扩展键 (PSTR) (0x01000000 & lParam ? "是" : "否"), //判断是否同时使用了ALT键 (PSTR) (0x20000000 & lParam ? "是" : "否"), (PSTR) (0x40000000 & lParam ? "按下" : "抬起"), //判断前一次击键状态 (PSTR) (0x80000000 & lParam ? "按下" : "抬起")) //判断转换状态 ); }
ShowKey函数首先定义了szFormat字符串,并 在其中针对字符消息和非字符消息定义了两种 不同的输出格式。 然后调用ScrollWindowEx 函数使显示区域滚屏,为信息输出作准备。 ScrollWindowEx函数的主要功能是使窗口编辑 区中的某一矩形区域产生滚屏效果。 ScrollWindowEx函数的原型定义如下: int ScrollWindowEx ( HWND hwnd, // 发生滚屏的窗口的句柄 int dx, // 水平滚屏的数值 int dy, // 垂直滚屏的数值 CONST RECT*prcScroll //记录发生滚屏的矩形区域的RECT结构体的地址 CONST RECT* prcClip, //记录发生剪切的矩形区域的 RECT结构体的地址 HRGN hrgnUpdate,// 需要更新区域的句柄 LPRECT prcUpdate, // 记录需要更新矩形区域的 RECT结构体的地址 UINT flags // 滚屏控制标志 );
其中,dx参数给出了以设备单位尺寸 (对于显示器为像素)为单位的每一次 水平滚屏的度量值。dx参数取正值表示 向右滚屏,取负值表示向左滚屏。如参数 给出了以设备单位尺寸(对于显示器为 像素)为单位的每一次垂直滚屏的度量值。 如参数取正值表示向下滚屏,取负值表示 向上滚屏。dx和dy两个参数不能同时取非零值,也就是说,ScrollWindowEx函数不能使编辑区同时向水平和垂直方向滚屏。 prcScroll参数为一个指向记录滚屏的矩形区域的RECT结构体变量的指针,如果取值为NULL,则整个编辑区发生滚屏。 hrgnUpdate参数为因滚屏而变得无效的矩形区域的句柄,多数情况下可以取NULL。 prcUpdate参数指向一个记录因为滚屏而变得无效的矩形区域的 RECT结构体变量。多数情况下取NULL。
flags变量可以通过不同的取值来控制滚屏的 状况,其取值和意义如下所示。 SW_ ERASE当和 SW_INVALIDATE值 同时使用时,会通过向 window发送 一个 WM_ ERASEBKGND消息将最近变得无效 的区域抹去; SW_INVALIDATE在发生滚屏后使由hrgnUpdate参数指定的区域无效; SW_SCROLLCHILDREN使所有的子窗口都发生滚屏; SW_ SMOOTHSCROLL在 Windows 95及以后的版本中使窗口发生平滑滚屏。如果ScrollWindowEx函数执行成功,则返回值为以下三者之一: SIMPLEREGION表示有一个矩形的无效区域; COMPLEXREGION表示没有无效区域和重叠区域; NULLREGION表示没有无效区域。 如果ScrollWindowEx函数执行不成功,则返回ERROR。
ScrollWindowEx函数的功能也可以通过 ScrollWindow函数来实现,ScrollWindow 函数的原型定义如下: BOOL Scrollwindow( HWND hwnd //窗口句柄 int XAmount, // 水平滚屏的数值 int YAmount, // 垂直滚屏的数值 CONST RECT* lpReCt, //记录发生滚屏的矩形区域的 RECT结构体的地址 CONST RECT* lpClipRect //记录发生剪切的矩形区域的 RECT结构体的地址 ); 可以看出,ScrollWindow函数与ScrollWindowEx函数十分相似,其参数的意义也基本相同。事实上,ScrollWindow函数是为了保持对较低版本的Windows兼容而设计的,用户在编程时,除非需要考虑程序的向下兼容,否则一般都应使用ScrollWindowEx函数。