您好,欢迎访问三七文档
第2篇界面设计基础136第7章系统的输入设备鼠标和键盘是Windows系统基本的输入设备。Windows很大程度上是基于鼠标的操作系统,所有的Windows程序都应当响应鼠标输入,Windows98/2000操作系统本身也不例外。VisualC++6.0提供了大量的处理鼠标消息的函数,这些函数将在后面详细地讲到。键盘是用户把字符输入到计算机的设备,没有键盘就不能正常地运行Windows系统。在本章中,我们将介绍采用键盘和鼠标作为应用程序的基本输入设备时所涉及的基本概念和编程原则。7.1鼠标的应用在图形操作系统中,鼠标是最重要的输入设备之一。现在市场上常见的鼠标,根据工作原理不同可分为机械式鼠标、光电式鼠标和激光式鼠标;根据按键个数的不同,可以分为两键鼠标和三键鼠标。由于在Windows图形操作系统中,鼠标发挥了强大的威力,因而对它的控制与使用越来越受到用户的重视。好在Windows98/2000为用户提供了统一的鼠标编程接口,因而用户不必过多的了解其底层的知识,我们只针对不同的鼠标消息进行处理即可。接下来,我们将学习一些与鼠标相关的基本概念。7.1.1鼠标消息Windows是基于消息传递、事件驱动的操作系统。当用户移动鼠标、按下或释放鼠标键时,都会产生鼠标消息。根据鼠标所处的位置不同——窗口的客户区或非客户区,Windows系统产生的鼠标消息分为两大类:客户区域的鼠标消息、非客户区域的鼠标消息。1.客户区域鼠标消息当鼠标指针通过应用程序窗口的客户区域时,Windows会发送客户区域鼠标消息到应用程序中。客户区域鼠标消息是用户可以在Windows应用程序中正常处理的信息。例如,当用户移动鼠标通过应用程序窗口的客户区域(在应用程序中能画图的窗口区域)时,应用程序会接收一连串的WM_MOUSEMOVE消息,这些消息不仅告诉应用程序鼠标在移动,而且还告诉应用程序在Windows产生消息时鼠标的位置。当鼠标移动到应用程序窗口的客户区域外面时,应用程序则停止接收客户区域的鼠标消息,而Windows会把鼠标消息发送给鼠标碰巧通过的元素(包括桌面)。当鼠标移回到窗口第7章系统输入设备137的客户区域时,Windows会重新把鼠标消息发送方向指向应用程序(在应用程序已经捕获了鼠标时例外,这意味着即使当鼠标位于该应用程序窗口外,Windows也指示发送所有鼠标消息给该应用程序)。应用程序可以接收十种客户区域鼠标消息,表7-1列举了这些消息和关于它们的描述。表7-1客户区域鼠标按键消息消息说明WM_LBUTTONDBLCLK鼠标左键被双击WM_LBUTTONDOWN鼠标左键被按下WM_LBUTTONUP鼠标左键被释放WM_MBUTTONDBLCLK鼠标中间键被双击WM_MBUTTONDOWN鼠标中间键被压下WM_MBUTTONUP鼠标中间键被释放WM_MOUSEMOVE鼠标移动穿过客户区域,可用表3-4的值WM_RBUTTONDBLCLK鼠标右键被双击WM_RBUTTONOWN鼠标右键被压下WM_RBUTTONUP鼠标右键被释放2.非客户区鼠标消息在Windows中,除了客户区以外的部分都是非客户区,Windows会给应用程序发送非客户区域鼠标消息。当鼠标通过除客户区域以外的应用程序窗口的任何区域时,就会产生与客户区域鼠标消息相类似的鼠标消息。例如,当鼠标通过窗口的标题栏或控制按钮时,应用程序会接收非客户区域鼠标消息。大部分应用程序不处理非客户区域鼠标消息,因为它们可以被Windows操作系统本身妥善地处理。例如,当用户双击窗口的标题栏时,Windows会使窗口的尺寸大小恢复到它原有的设置。通常,读者不要干涉Windows对非客户区域鼠标消息的默认处理。因为如果干涉了这种处理时,应用程序的窗口也许会被冻结,不能按用户所期望的情况响应用户。然而,有时当响应非客户区域时,鼠标消息会使用程序执行额外的功能,例如应用程序也许会为增强窗口工具栏响应鼠标的方式而捕获非客户消息。一般情况下,应用程序不必考虑非客户区域鼠标消息。然而,为了防止遇到麻烦,有的应用程序可以接收十个非客户区域鼠标消息,如表7-2所示,它们和客户区域的消息类似。表7-2非客户区域鼠标按键消息消息说明WM_NCLBUTTONDBLCLK鼠标左健被双击第2篇界面设计基础138WM_NCLBUTTONDOWN鼠标左键被按下续表消息说明WM_NCLBUTTONUP鼠标左键被释放WM_NCMBUTTONDBLCLK鼠标中键被双击WM_NCMBUTTONDOWN鼠标中间键被按下WM-NCMBUTTONUP鼠标中键被释放WM-NCMOUSEMOVE鼠标在客户区域内移动WM-NCRBUTTONDBLCLK鼠标右键被双击WM-NCRBUTTONDOWN鼠标右键被按下WM-NCRBUTTONUP鼠标右键被释放7.1.2鼠标消息处理MFC把鼠标消息处理函数封装在CView类中,这些函数都是虚函数,它们分别是:OnMouseMove(UINTnFlag,CPointpoint);//鼠标移动消息处理函数OnLButtonDown(UINTnFlag,CPointpoint);//鼠标左键按下消息处理函数OnLButtonUp(UINTnFlag,CPointpoint);//鼠标左键弹起消息处理函数OnLButtonDblClk(UINTnFlag,CPointpoint);//鼠标左键双击消息处理函数……它们分别对应鼠标消息:MW_MOUSEMOVEMW_LBUTTONDOWNMW_LBUTTONUP……以上这些消息处理函数的point参数代表鼠标热点的坐标位置,point.x为横坐标,point.y为纵坐标。这里采用的是客户坐标系统。在这个坐标系统中,默认的坐标原点(0,0)位于客户区的左上角。nFlags参数中包含了鼠标按钮和键盘组合使用标志,用来描述鼠标按钮和键盘上Shift键和Ctrl键的组合状态:(1)MK_LBUTTON:鼠标左键被按下,与WM_LBUTTONDOWN所处状态相同。(2)MK_RBUTTON:鼠标右键被按下,与WM_RBUTTONDOWN所处状态相同。(3)MK_MBUTTON:鼠标中键被按下,与WM_MBUTTONDOWN所处状态相同。(4)MK_SHIFT:键盘上的Shift键被按下。第7章系统输入设备139(5)MD_CONTROL:键盘上的Ctrl键被按下。若想知道某个按钮是否被按下,可用对应的位屏蔽值与nFlags参数作按位逻辑“与”运算,所得结果若为非零值,则表示按钮被按下,如:if(nFlags&MK_LBUTTON)AfxMessageBox(“Lbuttonispresseddown!”);elseAfxMessageBox(“Lbuttonisup!”);这里需要说明的是,如何区分两次单击和一次双击,这取决于两次按下按钮之间的时间间隔,只有当时间间隔小于一定值时才被认为是一次双击,Windows默认的时间间隔为500毫秒,应用程序可以调用::SetDoubleClickTime()函数来重新设定该值。若要使窗口函数能接收到鼠标双击产生的消息,在注册窗口类时,必须指明该窗口具有CS_DBLCLKS风格,如:wndclass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;注意:如果窗口风格不包含CS_DBLCLKS,则即使进行了双击操作,该窗口也只能收到两条“WM_BUTTONDOWN”消息和两条“WM_BUTTONUP”消息。7.1.3改变鼠标指针的形状向用户提供反馈最明显的方法之一就是改变鼠标指针的形状。在惯用的指针中,沙漏光标指针是最易于显示的,这是因为MFC类库提供了两个非常有用的函数,其中一个函数BeginWaitCursor()用于显示沙漏光标指针,另一个函数EndWaitCursor(),用于将指针恢复成正常的形状。两个函数均应在长时间的执行巨大的磁盘I/O访问任务时调用。应该指出的是,这并不是显示沙漏光标指针的唯一途径,用户同样可以通过处理WM_SETCURSOR消息来显示沙漏光标指针。如果在持续显示沙漏光标指针时,程序需要与用户进行交互,即提取任意类型的消息,那么就必须响应WM_SETCURSOR的处理。Windows98/2000向每一个窗口发送持续的消息流,从而引起每一个窗口指针的持续更新。用于显示指针所调用的函数是Windows98API函数SetCursor(),例如用以显示箭头光标代码行为:::SetCursor(::LoadCursor(AfxGetInstanceHandle(),//返回标识当前应用程序对象的句柄IDC_ARROW));//箭头光标值Windows系统提供的标准鼠标指针形状如表7-3所示。表7-3系统光标指针光标形状值描述IDC_ARROW标准的箭头光标(选择)IDC_CROSS十字形光标(通常用于精确定位)IDC_SIZEALL四箭头光标(移动)IDC_SLZEWE横向双箭头光标(水平调整)IDC_SIZENS纵向双箭头光标(垂直调整)IDC_SIZENWSE正斜向双箭头光标(正斜向调整)第2篇界面设计基础140IDC_SIZENESW反斜向双箭头光标(反斜向调整)IDC_UPARROW垂直箭头光标续表光标形状值描述IDC_IBEAMⅠ形文本光标(选择文字)IDC_WAIT漏斗形计时等待光标(等待)IDC_APPSTARTING箭头加漏斗光标(后台运行)IDC_NO圆加反斜线的光标(禁区、不可作为拖放目的)7.1.4捕捉鼠标有时候用户需要把鼠标消息集中在一个窗口中。这可以通过捕捉鼠标来完成上面的工作。尽管读者也许会认为鼠标的捕捉从某种程序上会限制指针的移动,其实不然。相反,捕捉鼠标会强迫所有的鼠标消息被送到一个窗口内。窗口在捕捉了鼠标后,可以继续获得鼠标的输入,尽管此时指针已不落在此窗口中。窗口究竟需要在什么时候进行鼠标捕捉呢?当一个鼠标消息——通常是左键被按下的消息(WM_LBUTTONDOWN)——启动了一个需要多个鼠标消息操作时,捕捉鼠标是非常必要的。例如拖放、拖动来选择多个项(如在字处理器中的多行),以及通过拖动来绘图时必须捕捉鼠标。如果在没有让应用程序知道鼠标键已弹起的消息时,鼠标可能已经离开,此时应用程序将处于一种模糊状态。毕竟,当多个鼠标消息操作开始时,用户很可能已经设置了许多标志来表明操作正在发生。用户希望在前进中避免操作突然停止,也就是说,对于强迫鼠标停住直到它完成已经开始的工作时捕捉鼠标是很有必要的。理解鼠标的捕捉有助于观察鼠标的操作。运行某个应用程序,并打开File/Open对话框,鼠标将被两个对话框控件所捕捉,这两个控件是列表框和编辑控件。当用户单击已选择在列表框中的项或者在编辑控件中的文本时,捕捉鼠标将会发生。单击这样的控件后,当用户将鼠标拖动到边框外面时,可以看到控件在滚动它的内容,滚动是因为鼠标被捕捉而引起的。另一个可以看到鼠标被捕捉的地方是在大部分文本编辑窗口中(包括VisualC++的编辑器),当用户单击一个充满文本的窗口并拖动到越出窗口边界时,这些窗口会滚动,这些窗口能够连续地接到鼠标的输入(WM_MOUSEMOVE消息),这是因为鼠标已经被捕捉。现在,用户已经了解了鼠标的工作情况,可能想了解如何捕捉到鼠标。这是很简单的,用户只需调用CWnd::SetCapture()函数。正如曾经提到的,用户完成上述工作一般是响应一个鼠标按下消息,要释放鼠标捕捉则是调用CWnd::ReleaseCapture()函数,释放被捕捉鼠标的最好时间是响应鼠标键弹起的时候(WM_LBUTTONUP)。下面是一段ClassWizard生成的代码,它是鼠标捕捉与释放的典型方案。当鼠标左键被第7章系统输入设备141按下时,鼠标被捕捉(响应WM_LBUTTONDOWN消息),当鼠标左键弹起时,释放鼠标(响应WM_LBUTTONUP消息)。当用户捕捉鼠标时,Windows98/2000并不向用户传递任何击键测试(WM_NCHITTEST)或者光标形状设置(WM_S
本文标题:7-9章1
链接地址:https://www.777doc.com/doc-2956902 .html