吉春虎

导航

 
 

window消息机制

分类: VC/MFC 1556人阅读 评论(2) 收藏 举报

windows是基于事件和消息的操作系统,要学习windows编程,必须要了解事件和消息机制。

一、什么是消息

通俗地讲就是操作系统发送给应用程序的一个通知,它告诉应用程序一个事件的发生。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给相应的应用程序。

二、消息的组成

消息本身是作为一条记录传送给应用程序的,这个记录类型叫做TMsg。TMSG记录由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)以及其他信息组成。

在Delphi的Windows单元中是这样声明的:  type  TMsg = packed record  hwnd: HWND; / /窗口句柄  message: UINT; / /消息常量标识符  wParam: WPARAM ; // 32位消息的特定附加信息  lParam: LPARAM ; // 32位消息的特定附加信息  time: DWORD; / /消息创建时的时间  pt: TPoint; / /消息创建时的鼠标位置  end ;其中TPoint定义如下:  TPoint= record  x:integer;  y:integer;  end;

在C语言中的定义如下:  typedef struct Msg  {  HWND hwnd; / /窗口句柄  UINT message; / /消息常量标识符  WPARAM wParam; // 32位消息的特定附加信息  LPARAM lParam; // 32位消息的特定附加信息  DWORD time; / /消息创建时的时间  TPoint pt; / /消息创建时的鼠标位置  } TMsg;  typedef struct TPoint  {  int x;  int y; 
  }TPoint;
三、消息记录(TMSG)中各个字段的意义
hwnd:32位的窗口句柄。所谓窗口句柄就是操作系统为了区分系统中的众多窗口而为每个窗口分配的一个32位的标识符,系统通过窗口句柄来在整个系统中唯一标识一个窗口。
message:用来区别其他消息的常量。这些常量可以是windows系统预定义的常量,也可以是用户自定义的常量。
wparam:32位,通常是一个与消息有关的常量,也可能是窗口或控件的句柄。
lparam:32位,通常是一个指向内存中数据的指针。
time:消息创建时的时间。
pt:消息创建时鼠标的位置。
四、windows消息系统的组成
Windows的消息系统是由3个部分组成的:  1)消息队列。Windows能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取       消息,然后分派给某个窗口。  2)消息循环。通过这个循环机制应用程序从消息队列中检索消息,再把它分派给适当的窗口,然       后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。  3)窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后       响应它。窗口过程是一个回调函数;处理了一个消息后,它通常要返回一个值给Windows。
       注意回调函数是程序中的一种函数,它是由Windows或外部模块调用的。
Windows消息控制中心一般是三层结构,其顶端就是Windows内核。Windows内核维护着一个消息队列,第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级窗体(Window)或控件(Control)。第二级控制中心一般是各Windows应用程序的Application对象。第三级控制中心就是Windows窗体对象,每一个窗体都有一个默认的窗体过程,这个过程负责处理各种接收到的消息。
(注:windows指windows操作系统;窗口:即windows窗口;窗体:包括窗口,以及有句柄的控件;control指控件,控件本身也可能是一个window,也可能不是;Application即应用程序,应用程序也可能不会用到Windows消息机制,这里我们专门讨论有消息循环的应用程序)
五、消息分类

Windows操作系统中包括以下几种消息:

  1、标准Windows消息:

  这种消息以WM_打头。

  2、通知消息

  通知消息是针对标准Windows控件的消息。这些控个包括:按钮(Button)、组合框(ComboBox)、编辑框(TextBox)、列表框(ListBox)、ListView控件、Treeview控件、工具条(Toolbar)、菜单(Menu)等。每种消息以不同的字符串打头。

  3、自定义消息

 编程人员还可以自定义消息。 
六、句柄
不是每个控件都能接收消息、转发消息和绘制自身,只有具有句柄(handle)的控件才能做到。有句柄的控件本质上都是一个窗体(window),它们可以独立存在,可以作为其它控件的容器,而没有句柄的控件,如Label,是不能独立存在的,只能作为窗口控件的子控件,它不能绘制自身,只能依靠父窗体将它绘制来。  句柄的本质是一个系统自动维护的32位的数值,在整个操作系统的任一时刻,这个数值是唯一的。但该句柄代表的窗体释放后,句柄也会被释放,这个数值又可能被其它窗体使用。也就是说,句柄的数值是动态的,它本身只是一个唯一性标识,操作系统通过句柄来识别和查找它所代表的对象。  然而,并非所有的句柄都是窗体的句柄,Windows系统中还中很多其它类型的句柄,如画布(hdc)句柄,画笔句柄,画刷句柄,应用程序句柄(hInstance)等。这种句柄是不能接收消息的。但不管是哪种句柄,都是系统中对象的唯一标识。
  那为什么句柄使窗口具有了如此独特的特性呢?实际是都是由于消息的原因。由于有了句柄,窗体能够接收消息,也就知道了该什么时候绘制自己,绘制子控件,知道了鼠标在什么时候点击了窗口的哪个部分,从而作出相应的处理。句柄就好像是一个人的身份证,有了它,你就可以从事各种社会活动;否则的话,你要么是一个社会看不到的黑户,要么跟在别人后面,通过别人来证明你的存在。
七、消息的传递
1、从消息队列获取消息:  可以通过PeekMessage或GetMessage函数从Windows消息队列中获取消息。Windows保存的消息队列是以线程(Thread)来分组的,也就是说每个线程都有自己的消息队列。2、发送消息  发送消息到指定窗体一般通过以下两个函数完成:SendMessage和PostMessage。两个函数的区别在于:PostMessage函数只是向线程消息队列中添加消息,如果添加成功,则返回True,否则返回False,消息是否被处理,或处理的结果,就不知道了。而SendMessage则有些不同,它并不是把消息加入到队列里,而是直接翻译消息和调用消息处理(线程向自己发送消息才是这样),直到消息处理完成后才返回。所以,如果我们希望发送的消息立即被执行,就应该调用SendMessage。  还有一点,就是SendMessage发送的消息由于不会被加入到消息队列中(错:线程向其他线程发送消息也是追加到其他线程的发送消息队列的,即使这两个线程在同一个进程也是如此),所以通过PeekMessage或GetMessage是不能获取到由SendMessage发送的消息。  另外,有些消息用PostMessage不会成功,比如wm_settext。所以不是所有的消息都能够用PostMessage的。  还有一些其它的发送消息API函数,如PostThreadMessage,SendMessageCallback,SendMessageTimeout,SendNotifyMessage等。

 

 
 
 
 
 
 
 
 
 
 
 
 
 
posted on 2013-09-13 10:57  吉春虎  阅读(266)  评论(0编辑  收藏  举报