windows消息机制.doc_第1页
windows消息机制.doc_第2页
windows消息机制.doc_第3页
windows消息机制.doc_第4页
windows消息机制.doc_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

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

文档简介

windows消息机制消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。 基于windows的应用程序是基于事件驱动的。他们不会显式地调用函数获得输入,而是等待操作系统把输入传给应用程序。一个消息从产生到被一个窗口响应,其中有5个步骤:1) 系统中发生了某个事件。2) Windows把这个事件翻译为消息,然后把它放到消息队列中。3) 应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中。4) 应用程序把消息传递给一个适当的窗口的窗口过程。5) 窗口过程响应这个消息并进行处理。一、消息类型消息主要分为两种:一是系统定义消息;二是自定义消息。(1)系统定义消息 每一个系统定义消息都有一个唯一的消息标识符和相对应的符号常量(在系统SDK的头文件中定义的),这些标识符和常量代表着消息意图。常量的前缀代表着可以解释处理消息的窗口的类型,一般情况下,第一个字母为控件的头一个字母,第二个字母是M的是消息(Message)常量,S是风格(Style)常量,N是通知、事件(Notify)。下面列出系统定义消息的前缀所代表的消息类别的清单。Prefix Message categoryABMApplication desktop toolbarBMButton controlCBCombo box controlCBEMExtended combo box controlCDMCommon dialog boxDBTDeviceDLDrag list boxDMDefault push button controlDTMDate and time picker controlEMEdit controlHDMHeader controlHKMHot key controlIPMIP address controlLBList box controlLVMList view controlMCMMonth calendar controlPBMProgress barPGMPager controlPSMProperty sheetRBRebar controlSBStatus bar windowSBMScroll bar controlSTMStatic controlTBToolbarTBMTrackbarTCMTab controlTTMTooltip controlTVMTree-view controlUDMUp-down controlWMGeneral window在SDK中事先定义好的消息,非用户定义的,其范围在0x0000, 0x03ff之间, 还可以分为以下三类:1窗口消息(Windows Message) 与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等。可以是一般的窗口,也可以是Dialog,控件等。如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL.2命令消息(Command Message)与处理用户请求有关, 如单击菜单项或工具栏或控件时, 就会产生命令消息。WM_COMMAND, LOWORD(wParam)表示菜单项,工具栏按钮或控件的ID。如果是控件, HIWORD(wParam)表示控件消息类型3 控件通知(Notify Message) 控件通知消息, 这是最灵活的消息格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHDR的指针。NMHDR包含控件通知的内容, 可以任意扩展。(2)程序定义消息用户自定义的消息, 对于其范围有如下规定:WM_USER: 0x0400-0x7FFF (ex. WM_USER+10)WM_APP(winver4.0): 0x8000-0xBFFF (ex.WM_APP+4)RegisterWindowMessage: 0xC000-0xFFFF 应用程序定义消息的消息标识符取值定义规则应该遵循如下原则:A.系统对0x0000到0x03ff(WM_USER-1)都保留为系统定义消息,因此应用程序不能使用这些值来定义应用程序定义消息。B.取值范围为0x0400(WM_USER)-0x7FFF,可以用来定义自定义消息的消息标识符取值。C.假如你的应用程序是在4.0上的系统运行,那么你可以使用0x8000(WM_APP)-0xBFFF范围的值作为私有消息的标识符取值。D.当应用程序调用RegisterWindowMessage函数来注册一个消息的时候,系统会返回一个消息标识符给你,范围在0xC000-0xFFF之间。这个函数返回的标识符可以确保在整个系统是唯一的。这个函数的使用可以防止和其他应用程序使用的自定义消息发生冲突。 对于windows来说,当调用getMessage或PeekMessage时,按下列顺序从消息队列中获得消息进行处理: 1)首先处理sendMessage发送的发送消息WM_SENDMESSAGE 2)接着处理PostMessage发送的登记消息WM_POSTMESSAGE 3)检查是否有退出消息WM_QUIT 4)处理虚拟输入消息队列 WM_INPUT 5)如果有重绘消息,就处理 WM_PAINT 6)如果定时消息,就处理 WM_TIMER注意:这个表格所列的消息为windows系统的关键消息事件消息 发生时间OnActivateWM_ACTIVATE 被激活时OnClickWM_XBUTTONDOWN 单击鼠标时OnCreateWM_CREATE 新创建时OnDblClickWM_XBUTTONDBLCLICK 双击鼠标时OnKeyDownWM_KEYDOWN 键盘键被按下时OnKeyPressWM_CHAR 键盘输入时OnKeyUpWIN_KEYUP 键盘键弹起时OnPaintWM_PAINT 重绘时(低级)OnResizeWM_SIZE 大小改变时(后于WM_CREATE)OnTimerOnDestoryOnQuitWM_TIMER 时间改变时(低级)WM_DESTORY 窗口被毁时WM_QUIT 退出时(低级) 二、消息传递系统使用两个方法来传递消息给窗口过程:一种是投递到消息队列,还有一种就是投递消息到系统定义的一个内存对象临时存储,并且直接把这个消息发送给窗口过程(这个方法不会进入消息队列)。需要投递到消息队列的消息称为队列化消息。他们主要是用户通过键盘或者鼠标输入,例如WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_KEYDOWN和WM_CHAR消息。其他队列化消息还包括时钟,绘制和退出消息:WM_TIMER,WM_PAINT,WM_QUIT.其他直接发送给窗口过程的消息称为非队列化消息。(1)队列化消息对于每一个正在执行的Windows应用程序,Windows为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。系统投递消息到线程消息队列的方式是先填写一个MSG结构体,然后把这个结构体COPY到消息队列中。线程也可以投递消息到他自己的消息队列或者其他线程的消息队列,使用PostMessage或者PostThreadMessage函数。MSG结构在头文件中定义如下: typedef struct tagMSG HWND hwnd; /消息将要发送到的那个窗口的句柄,用这个参数可以决定让哪个窗口接收消息。UINT message; /消息号,它唯一标识了一种消息类型。每种消息类型都在Windows文件进行了预定义。 WPARAM wParam; /一个32位的消息参数,这个值的确切意义取决于消息本身。LPARAM lParam; /一个32位的消息参数,这个值的确切意义取决于消息本身。DWORD time; /消息放入消息队列中的时间,在这个域中写入的并非当时日期,而是从Windows启动后所测量的时间值。Windows用这个域来使用消息保持正确的顺序。 POINT pt; /消息放入消息队列时的鼠标坐标 MSG, *PMSG; 应用程序通过调用GetMessage函数从他的消息队列中取出一个消息,如果想分析一个消息,但是又不想从消息队列中移除,那么可以使用PeekMessage函数,这个函数会根据消息的内容重新给你填写一个MSG返回给你,队列中的消息不受影响。(2)非队列化消息非队列化消息会绕过系统消息队列和线程消息队列直接发动给目标窗口过程函数,一般系统发送非队列化消息是为了通知受到事件影响的窗体。例如,当用户激活了一个新的应用程序窗口,系统会发送一系列的消息,包括WM_ACTIVATE,WM_SETFOCUS,WM_SETCURSOR。三、消息处理 应用程序必须对投递在他的线程队列中的消息进行取出和处理。单线程的应用程序通常在WinMain函数使用一个消息循环来取出消息,发送消息给对应的窗口过程函数来对消息进行处理。多线程的应用程序在每个创建窗口的线程中都可以包含一个消息循环。(1)消息循环消息循环标准写法如下:MSG msg;BOOL bRet;while( (bRet = GetMessage( &msg, NULL, 0, 0 ) != 0)if (bRet = -1)/ handle the error and possibly exitelseTranslateMessage(&msg);DispatchMessage(&msg);很多人常犯的一个错误是把循环判断写成:while(GetMessage( &msg, NULL, 0, 0 ),这样写是不严谨的。因为GetMessage可能返回-1,0,非0三种状态。-1表示函数调用出错,如果这样写,当返回-1的时候也会进入消息循环,而里面无法对返回值为-1的情况作出错误处理,会导致出错。消息循环必须采用TranslateMessage函数把虚拟键消息转换成字符消息(WM_CHAR)并且把这个字符消息重新放回到应用程序的消息队列。然后这个字符消息会按照输入的顺序被取出来,并且发给窗口过程函数进行处理。当从消息队列中取出消息之后,应用程序可以使用DispatchMessage函数触发系统把这个消息发送给窗口过程函数进行处理。DispatchMessage函数需要输入一个指向MSG结构的指针(当然这个MSG结构可以是以前GetMessage或者PeekMessage获得的)。DispatchMessage会传送窗口句柄,消息标识符,两个消息参数给窗口过程函数,但是他不会传送时间和鼠标位置信息。应用程序在处理消息的时候可以通过调用GetMessageTime和GetMessagePos函数获得这两个信息。(2)窗口过程每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后响应它。窗口过程是一个回调函数;处理了一个消息后,它通常要返回一个值给Windows。因为窗口过程是被属于同一个类的所有窗口共享的,所以他能为几个不同的窗口处理消息。为了识别受消息影响的特定窗体,窗口过程可以检查窗口句柄来识别。(3)消息过滤应用程序在调用GetMessage或者PeekMessage函数的时候,是可以选择特定消息的,这就称为消息过滤。过滤器是通过设置函数中的消息标识符范围(从开始到结束某个范围)或者窗口句柄来实现的,当然同时设置也可以的。消息过滤机制对于想搜寻消息队列寻找在队列后面的消息很有用,如果应用程序必须优先处理输入(硬件)消息,消息过滤也比较有用。WM_KEYFIRST和WM_KEYLAST常量可以用来作为对所有键盘消息的过滤范围值;WM_MOUSEFIRST和WM_MOUSELAST常量可以用来作为所有鼠标消息的过滤范围值。任何过滤消息的应用程序必须确保满足过滤条件的那些消息能被投递。例如,如果一个应用程序为WM_CHAR消息设置过滤,那么这个窗口就不会接受任何键盘输入,GetMessage函数不会返回任何键盘消息,这相当于“挂起”了应用程序。(4)投递和发送消息任何应用程序都可以投递和发送消息。和系统的机制一样,投递消息是把消息结构COPY到消息队列中,发送消息是给窗口过程传递一个消息参数的方式进行。为了投递消息,应用程序使用PostMessage函数。发送消息,一般是用SendMessage,BroadcastSystemMessage, SendMessageCallback,SendMessageTimeout,SendNotifyMessage,or SendDlgItemMessage函数。 (A)投递消息应用程序一般是投递一个消息来通知指定窗口完成某个任务。PostMessage创建一个MSG结构,并COPY到消息队列中。应用程序的消息循环最终都会取出消息并且发送给对应的窗口过程。如果PostMessage中消息没有指定窗口句柄(为NULL),那么消息会被投递到当前线程的消息队列中。因为没有窗口句柄,所以应用程序必须处理这个消息,这是创建一个供整个应用程序使用的消息的一个方法。如果PostMessage中窗口句柄为HWND_TOPMOST,那么就表

温馨提示

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

评论

0/150

提交评论