第三章 1 手写笔和触摸屏
Windows CE设备并不总是有鼠标的。作为替代,许多Windows CE设备都有触摸屏和手写笔。
鼠标消息
鼠标光标无论在什么时候移过屏幕,光标下的最顶层窗口都会收到一个WM_MOUSEMOVE消息。如果用户点鼠标左键或者右键,窗口会收到WM_LBUTTONDOWN或WM_RBUTTONDOWN消息;而当用户释放按键时,窗口则会收到WM_LBUTTONUP或WM_RBUTTONUP消息。如果用户按下并释放鼠标滚轮,窗口会收到WM_MBUTTONDOWN及WM_MBUTTONUP消息。
对所有这些消息,wParam和lParam都具有相同的值。wParam包含一个标志位集合,用来指出当前键盘上Ctrl或Shift键是否被按下。同Windows 的其它版本一样,在这些消息里没有提供Alt键的状态。要想获得消息发送时Alt键的状态,可以使用GetKeyState函数。
lParam包含两个16位的值,用来指出点击点在屏幕上的位置。低16位是相对窗口客户区左上角的x(水平)坐标位置,高16位是y(垂直)坐标位置。
如果用户双击,也就是在预定义的时间内在屏幕同一位置点两次,Windows会向被双击的窗口发送WM_LBUTTONDBLCLK消息,不过只有当窗口类注册了CS_DBLCLKS风格时才会这么做。可以在用RegisterClass注册窗口类时设置类风格。
您可以通过对比发送给窗口的消息来区分单击和双击。当双击发生时,窗口首先收到来自最初单击的WM_LBUTTONDOWN和WM_LBUTTONUP消息。
接下来一个WM_LBUTTONDBLCLK消息会在WM_LBUTTONUP后发出。一个技巧是,禁止用任何方式响应WM_LBUTTONDOWN消息,因为这会阻止随后的WM_LBUTTONDBLCLK消息。通常来说这没什么问题,因为单击通常是选择一个对象,而双击则是启动一个对象的默认行为。
如果用户滚动鼠标轮,窗口会收到WM_MOUSEWHEEL消息。对于该消息,lParam的内容和其它鼠标消息的内容一样,都是鼠标光标的水平和垂直位置。wParam的低字位也是同样的位标志,指出当前被按下的键。但wParam的高字位则包含的是滚轮的距离,用常量WHEEL_DELTA的倍数来表示滚动的距离。如果该值为正,表示滚轮是朝远离用户方向滚动;如果该值为负,表示滚轮是朝用户方向滚动。
使用触摸屏
触摸屏和手写笔这一组合对Windows平台来说相对是比较新的,但幸运的是,要把它们集成到Windows CE应用程序里相对还是比较容易的。处理手写笔的最好方法就是把它看成是一个单键鼠标。手写笔产生的鼠标消息,同其它版本的Windows以及有鼠标的Windows CE里鼠标提供的消息相同。鼠标和手写笔的不同在于这两种输入设备的物理实体的不同。
和鼠标不同,手写笔没有光标来指示其当前位置。因此,手写笔不能像鼠标光标那样在屏幕的一个点上盘旋。当用户将光标移过一个窗口而不按鼠标键的话,光标就会盘旋。这个概念不适用于手写笔编程,因为当手写笔不和屏幕接触的时候,触摸屏是检测不到手写笔的位置的。
手写笔和鼠标之间的差异带来的另一个后果是:没有鼠标光标,那么应用程序不能通过改变盘旋光标的外貌来给用户提供反馈。基于触摸屏的Windows CE系统为这种典型的Windows反馈方式提供了光标设置功能。提示用户必须等待系统完成处理的沙漏光标,在Windows CE下得到支持,应用程序可以通过SetCursor函数来显示繁忙的沙漏,这和其它版本的Windows里的应用程序使用的方式一样。
手写笔消息
当用户用手写笔在屏幕上压触时,压触点下的顶层窗口如果此前没有输入焦点的话就会收到焦点,随后收到WM_LBUTTONDOWN消息。当用户抬起手写笔时,窗口会收到WM_LBUTTONUP消息。在手写笔按下的同时在同一个窗口内移动它,窗口就会收到WM_MOUSEMOVE消息。
电子墨水
对手持设备来说最典型的应用是捕捉屏幕上用户在的笔迹并存储下来。这个过程不是手写识别,只是简单的墨迹存储。在开始阶段,完成这个功能的最好方法应该是存储由WM_MOUSEMOVE消息传入的手写笔的各个点。但有个问题,就是有时候这些小型CE设备不能快速的发送消息,导致不能获得满意的分辨率。因此在Windows CE下,增加了一个函数来帮助程序员追踪手写笔。
BOOL GetMouseMovePoints (PPOINT pptBuf, UINT nBufPoints, UINT *pnPointsRetrieved);
GetMouseMovePoints返回没有产生WM_MOUSEMOVE消息的手写笔点数。函数参数包括点数组、数组大小和一个指向整数的指针,用来接收返回给应用程序的点数。一旦接收完,这些附加的点可以用来填充上一个WM_MOUSEMOVE消息和当前WM_MOUSEMOVE消息之间的空白。
GetMouseMovePoints产生一条曲线。它是按触摸板的分辨率返回点的,而不是按屏幕的。触摸板的分辨率通常设置为屏幕分辨率的4倍,所以您需要把GetMouseMovePoints返回的坐标除以4来转换成屏幕坐标。额外的分辨率是用在手写识别之类的程序中的。