第15章 消息和命令_第1页
第15章 消息和命令_第2页
第15章 消息和命令_第3页
第15章 消息和命令_第4页
第15章 消息和命令_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第15章

消息和命令

Windows程序是基于消息的,用户与应用程序的所有交互都是通过发送消息来完成的。当使用MFC来创建Windows应用程序时,为了与用户交互,我们需要了解MFC是如何处理消息的。了解MFC的消息映射MFC的消息在程序中处理鼠标消息处理键盘消息定时器消息自定义消息

15.1与Windows进行通信

Windows与程序之间的通信是通过发送消息来实现的。在使用API函数编写的程序中,程序中包含一个消息循环和窗口过程函数来完成对Windows消息的响应。当使用MFC开发应用程序时,消息处理的大部分工作都由MFC来完成。MFC支持提供函数来处理感兴趣的各个消息,而忽略其他的消息。由于我们的应用程序是基于MFC类的,所以对消息的处理是由程序中类的成员函数来完成的。那么MFC是如何将特定的Windows消息与特定的成员函数相联系的呢?他们之间的关联是由消息映射建立的。消息映射是一个消息和成员函数相互关联的表,其中的每一项都记录了一个函数以及与该函数相关联的消息。当出现给定的消息时,将搜索消息映射,查找与该消息相关联的函数。

15.1.2处理不同类型的消息

消息的类型决定它的处理方式,在程序中要处量的消息可以分为4类:命令消息(WM_COMMAND)它们是由用户界面元素产生的,如菜单项。在命令消息中包含有命令的标识符ID,以区分具体的命令。Windows消息(WM_xxx)Windows消息的示例有表示需要重给窗口WM_PAINT,所有派生自CWnd的类都可以接受Windows消息WM_xxx。控件消息(WM_NOTIFY)控件向其父窗口发送的通知消息。自定义消息

用户可以自定义消息,在应用程序中主动发出,一般用于应用程序的某一部分内部处理。

对于Windows消息和控件消息来说,它们始终由派生于CWnd的类的对象处理。例如,框架窗口类和视图类派生于CWnd,所以它们可以利用成员函数处理Windows消息和控件消息。而应用程序类、文档类和文档模板类不是派生于CWnd,所以它们不能处理Windows消息和控件消息。

15.2获取鼠标输入

Windows有20多种消息来标识与鼠标有关的输入事件。这些消息可分为两个类:客户区鼠标消息和非客户区鼠标消息。客户区鼠标消息用来报告客户区里发生的事件,非客户区鼠标消息则用来报告鼠标在窗口的非客户区所做的动作。通常可以忽略非客户区内的事件,让Windows系统处理即可。我们主要关心的是鼠标在客户区内所做的动作。

15.2.1客户区鼠标消息

表15-1列出鼠标在客户区中会发生的鼠标消息。15.2.2非客户区鼠标消息

所谓非客户区就是窗口中客户区之外的区域,主要包括窗口的标题栏、菜单栏和滚动条等。当鼠标在窗口的非客户区上单击或移动时,Windows就会向窗口发送一个非客户区鼠标消息。非客户区鼠标消息与客户区鼠标消息类似,只是在客户区鼠标消息名前添加NC字符,如客户区鼠标消息WM_LBUTTONDOWN,相应地非客户区消息则为WM_NCLBUTTONDOWN。非客户区鼠标消息的消息映射宏也是客户区鼠标消息的基础上添加NC,例如:消息WM_NCLBUTTONDOWN对应的消息映射宏为ON_WM_NCLBUTTONDOWN,消息处理函数为OnNcLButtonDown()。可以在任何场合和时间内调用。表14-1列出部分常用的全局函数。

15.2.3WM_NCHITTEST消息

窗口在接收到一个客户区或非客户区鼠标消息之前,它会先接收到鼠标的屏幕坐标和WM_NCHITTEST消息。大多数应用程序不处理WM_NCHITTEST消息,而是让Windows处理它。Windows对WM_NCHITTEST消息的处理,首先使用鼠标坐标来确定鼠标所在窗口上的位置,然后再产生一个客户区或非客户区鼠标消息。

15.2.4鼠标滚轮消息现在Windows上使用的鼠标大部分都有一个滚轮,通过滚轮不需要单击滚动条就能滚动一个窗口。在滚轮滚动时,当前活动窗口将接收到WM_MOUSEWHEEL消息。MFC的CScrollView类为这些消息提供了默认的处理程序,可以自动地滚动窗口,但是如果想用鼠标滚轮消息滚动一个非CScrollView窗口,则必须自己处理WM_MOUSEWHEEL消息。

15.2.5捕获鼠标

在处理鼠标消息时经常会遇到一个问题,在接收鼠标键的按下消息后,并不一定会接收到该鼠标键的释放消息。例如,在一个绘图程序中,经常以鼠标按下点为起点,到鼠标被释放的点为终点,连接一条直线,这就是所谓的“橡皮筋”线。但是如果在用户释放鼠标键之前,将鼠标移至窗口客户区以外,这时会发生什么情况呢?应用程序将不会得到WM_LBUTTONUP消息,也将无法绘制两点之间的直线。为了解决这个问题,Windows允许应用程序“捕获”鼠标,即在接收鼠标键按下消息后,可以继续接收鼠标消息,而不管鼠标是否仍然在当前窗口客户区内,直到鼠标键被释放或撤销对鼠标的“捕获”。捕获取鼠标可以使用函数CWnd::SetCaptue()函数,撤销对鼠标的捕获时可以使用API函数::ReleaseCapture()。对这些函数的调用通常发生在鼠标键按下或释放的消息处理函数中

15.3获取键盘输入

Windows应用程序获取键盘输入与鼠标输入相同,都是通过消息传递。任何时候只要一个键被按下或释放,程序都会接收到一个消息。如果想要知道PageUp是否被按下,以便应用程序执行相应的操作,可以处理WM_KEYDOWN消息并检查PageUp键代码。如果想知道某键是否被释放,可以处理WM_KEYUP消息。对于那些可打印字符的键,可以不管键按下或释放,而直接处理WM_CHAR消息,它可以指出从键盘输入的字符。处理WM_CHAR消息而不是WM_KEYUP/WM_KEYDOWN消息可以简化字符处理过程,因为这样可以把其他事件以及击键时的环境条件,如Shift键是否按下,CapsLock是否打开等这些事情交由Windows处理。

15.3.1输入焦点

键盘和鼠标都是被所有应用程序共享的全局硬件资源。对于鼠标消息则是通过标识鼠标下的窗口,以确定给哪个窗口发送鼠标消息。而键盘消息则是发送到具有“输入焦点”的窗口。在任何时候,只有一个窗口具有输入焦点。通常有输入焦点的窗口是活动应用程序的主窗口。然而,输入焦点也可能属于主窗口的子窗口或对话框中的控件。Windows通过WM_SETFOCUS和WM_KILLFOCUS消息通知即将接收或失去焦点的窗口。在应用程序中可以使用CWnd::SetFocus()函数将输入焦点转移到另一个窗口,还可以使用静态的CWnd::GetFocus()函数获取当前拥用输入焦点的窗口。

15.3.2按键消息

Windows通过给拥用输入焦点的窗口发送WM_KEYDOWN和WM_KEYUP消息来报告键被按下还是被释放,这些消息通常称为按键消息。当一个键被接下时,有输入焦点的窗口会接收到WM_KEYDOWN消息,以及一个标识键的虚拟代码。当键被释放时,窗口会接收到WM_KEYUP消息。当一个键被按下时,如果有另外的键被按下并释放,那么刚产生的WM_KEYDOWN和WM_KEYUP消息将分开按下键产生的WM_KEYDOWN和WM_KEYUP消息。Windows按照发生的顺序报告键盘事件,因此只要检查进入应用程序的按键消息流,就可以知道在何时有什么输入。

15.3.3字符消息

字符消息对应键盘中的可打印字符,包括大写字母、小写字母、数字或标点符号。也就说,它们与在显示屏上看到的以及发送到打印机上的字符一致。如果依靠键盘按键的按下和释放消息来处理可打印字符,则会非常复杂,这其中会涉及到字符的大小写等到问题。WindowsAPI提供一个可以在虚拟键代码与字符消息WM_CHAR之间转换的函数。

15.3.4插入符

在文字处理程序中,为了提示用户已经启用键盘输入都会提供一个闪烁的竖直条,该竖直条称为插入符,它用来标记下一个字符插入的位置。表15-7列出8种创建和管理插入符的CWnd成员函数。

15.4定时器消息

使用定时器只需要了解两个函数:CWnd::SetTimer()和CWnd::KillTimer()。SetTimer()函数设置一个以指定间隔触发的定时器,KillTimer()函数则取消正在运行的定时器。定时器以两种方式通知应用程序间隔时间已到:一种是发送WM_TIMER消息。另一种是调用应用程序定义的回调函数。这两种类型的定时器通知在被发送到应用程序时优先级很低,只有在消息队列没有其他消息时才会处理它们。

15.4.1WM_TIMER消息

设置定时器的最简单的方法是调用SetTimer()函数,它只需要两个参数:定时器ID和时间间隔。然后把WM_TIMER消息映射到应用程序窗口类中的一个OnTimer()函数。定时器ID是一个标识定时器的非零值。当OnTimer()函数响应WM_TIMER消息时,定时器ID会作为参数传入。如果只用了一个定时器,则ID值的意义不大。当使用两个以上的定时器,则需要使用ID值来区分不同的定时器。

15.4.2回调函数设置定时器

在调用SetTime()函数设置定时器时,如果在第三个参数中指定一个函数名称,则定时器不会触发WM_TIMER消息,而是调用指定的函数。设置回调函数的定时器如下:SetTimer(1,1000,TimerProc);回调函数TimerProc()的原型如下:voidCALLBACKTimerProc(HWNDhWnd,UINTmsg,UINTnTimerID,DWORDdwTime);因为回调函数是应用程序提供给Windows系统调用的函数,因此回调函数必须遵守事先规定好的参数格式和传递方式。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall或CALLBACK。

15.5自定义消息

由于自定义消息是用户根据自己的需要而定制的消息,因此用户需要手动添加事个消息处理过程。首先是定义用户消息的ID标识符,自定义消息ID值范围是有规定的,其值只能是介于WM_USER和0x7FFF之间。例如:constlongWM_USE

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论