春暖花开
雪化了,花开了,春天来了
posts - 149,comments - 125,trackbacks - 0

Windows 消息机制

编写Windows程序有两年了,但当别人问起Windows消息机制总觉得很难形容清楚。在这篇中,集合了很多我从网络中搜集来的一些知识,这里只是汇总一下。

我们编写的Windows程序是以事件为驱动,消息机制为基础的。对于每一个正在执行的Windows应用程序,Windows为其建立一个消息队列,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作消息循环的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。

一、消息循环

首先我们来看一下Windows消息循环。

while(GetMessage (&msg, NULL, 0, 0))       
{        
    TranslateMessage (&msg) ;        
    DispatchMessage (&msg) ;       
}

MSG结构在头文件中定义如下:

  typedef struct tagMSG

  {

  HWND hwnd;

  UINT message;

  WPARAM wParam;

  LPARAM lParam;

  DWORD time;

  POINT pt;

  } MSG, *PMSG;

  

其数据成员的具体意义如下:

hwnd:消息将要发送到的那个窗口的句柄,用这个参数可以决定让哪个窗口接收消息。

message:消息号,它唯一标识了一种消息类型。每种消息类型都在Windows文件进行了预定义。

wParam:一个32位的消息参数,这个值的确切意义取决于消息本身。

lParam:同上。

time:消息放入消息队列中的时间,在这个域中写入的并非当时日期,而是从Windows启动后所测量的时间值。Windows用这个域来使用消息保持正确的顺序。

pt:消息放入消息队列时的鼠标坐标。

消息循环以GetMessage调用开始,它从消息队列中取出一个消息。然后解释和分发消息。

二、消息类型

消息主要分为两种:一是系统定义消息;二是自定义消息。

1、系统定义消息(System-Defined Messages)

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 程序定义消息(Application-Defined Messages)
用户自定义的消息, 对于其范围有如下规定:
WM_USER: 0x0400-0x7FFF    (ex. WM_USER+10)
WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF

 

三、队列化消息和非队列化消息

消息被分成队列化消息和非队列化消息。

队列化消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化消息是在Windows的窗口过程中直接发送给窗口的消息处理程序。简单的说,队列化的消息被发送给消息队列,而非队列化的消息则发送给窗口消息处理程序。在任何情况下,窗口消息处理程序都将获得窗口的所有消息——包括队列化的和非队列化的。窗口消息处理程序是窗口的消息中心。队列化消息基本上是使用者输入的结果,如WM_KEYDOWNWM_KEYUPWM_CHARWM_MOUSEMOVEWM_LBUTTONDOWN WM_TIMERWM_PAINTWM_QUIT。非队列化消息则是其他消息。在许多情况下,非队列化的消息来自呼叫特定的windows函数。

四、SendMessagePostMessage的区别

SendMessagePostMessage是在编程过程中使用频率较高的两个函数。

SendMessage是同步的操作,它将消息发送给窗口,除非消息处理完毕,否则该函数不会返回。其返回值表示其他程序处理消息后的返回值。

PostMessage是异步的操作,将一个消息放到与指定窗口创建的线程相关的消息队列中,不等线程处理消息就返回。其返回值表示PostMessage是否执行成功。

五、GetMessagePeekMessage的区别

区别一:

peekmessage不管消息队列里有没有消息都会马上返回,有消息返回消息,没消息返回空值,

getmessage等待到有消息的时候才返回,

区别二:

peekmessage可以根据参数决定是否将消息保留在队列中,

PM_NOREMOVE:该参数指示保留消息

PM_REMOVE:该参数指示移去消息

getmessage获得消息后回把消息从消息队列中删去。

PeekMessage是一个异步的操作,而GetMessage则是一个同步的操作。

六、TranslateMessage

功能描述:将虚拟键消息转换为字符消息。字符消息被送到调用线程的消息队列中,在下一次线程调用函数GetMessagePeekMessage时被读出。

返回值:

 如果消息被转换(即,字符消息被送到线程的消息队列中),返回非零值。

如果消息是 WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP,返回非零值,不考虑转换。

如果消息没有转换(即,字符消息没被送到线程的消息队列中),返回值是零。

备注:

TranslateMessage函数不修改由参数lpMsg指向的消息。

TtanslateMessage仅为那些由键盘驱动器映射为ASCII字符的键产生WM_CHAR消息。

如果应用程序为其它用途而处理虚拟键消息,不应调用TranslateMessage函数。例如,如果TranslateAccelerator函数返回一个非零值,则应用程序将不调用TranslateMessage函数。

Windows CEWindows CE不支持扫描码或扩展键标志,因此,它不支持由TranslateMessage函数产生的WM_CHAR消息中的lKeyData参数(lParam16-24的取值。

TranslateMessage函数只能用于转换由GetMessagePeekMessage函数接收到的消息。


出处没有记载,简单汇总 

posted on 2009-04-29 08:02 Sandy 阅读(870) 评论(0)  编辑 收藏 引用 所属分类: Windows Mobile

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理