windows消息处理机制

消息


Windows程序设计是一种完全不同于传统的DOS方式的程序设计方式,它是一种事件驱动的程序设计模式,主要是基于消息的

例如,当用户在窗口窗口中画图的时候,按下鼠标左键,此时,操作系统会感知到这一事件,于是将这个事件包装成消息,投递到应用程序的消息队列中,然后应用程序从消息队列中取出消息并进行处理。在这个处理过程中,操作系统会调用程序中一个专门负责处理消息的函数进行处理,这个函数称为“窗口过程”。


消息是由MSG结构体来表示的,MSG结构体的定义如下:

 typedef struct tagMSG 
 {       
   HWND hwnd;			//消息所属的窗口
   UINT message;		//消息标识符
   WPARAM wParam;		//消息附加信息
   LPARAM lParam;		//消息附件信息
   DWORD time;			//消息投递到消息队列中的时间
   POINT pt;			//鼠标当前的位置
} MSG;

在windows中,消息是由一个数值来表示的,不同的消息对应一个不同的值。为了方便记忆,消息一般都定义成WM_XXX的形式(WM是Window Message的缩写),XXX是对应某种消息的英文拼写的大写形式。

例如:

#define WM_MOUSEMOVE                    0x0200  //鼠标移动
#define WM_LBUTTONDBLCLK                0x0203	//鼠标左键双击

消息队列


每一个Windows应用程序开始执行后,系统都会为程序创建一个消息队列,这个消息队列用来存放该程序创建的窗口的消息。Windows将产生的消息依次放到消息队列中去,而应用程序则通过一个消息循环不断地从消息队列中取出消息,并进行响应。这种消息机制,就是windows程序运行的机制。


消息处理机制


为了能够不断响应消息,应用程序需要编写一个消息循环,不断的从消息队列中获取消息,消息的获取需要用到GetMessage()函数。该函数的原型声明如下:

BOOL GetMessage(  
                LPMSG lpMsg,            //指向一个消息(MGS)的结构体
                HWND hWnd,              //指定接收哪个窗口的消息,若为NULL接收所有窗口
                UINT wMsgFilterMin,     //获取消息的最小值
                UINT wMsgFilterMax      //获取消息的最大值
                ); 

注意:

wMsgFilterMin和wMsgFilterMax通常都为0,表示接受所有的消息。GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT消息,该函数返回零。如果出现了错误,该函数返回-1例如,当参数hWnd是无效的窗口句柄或lpMsg是无效的指针时。


通常我们编写的消息循环代码如下:


while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)//Because the return value can be nonzero, zero, or -1,遇到WM_QUIT退出
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit,异常情况处理
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

TranslateMessage


该函数的作用是将虚拟键消息转换为字符消息,字符消息被投递到调用线程的消息队列中,当下一次调用GetMessage函数时被取出。

例如:

当我们敲击键盘上的某个字符键时,系统将产生WM_KEYDOWN和WM_KEYUP消息,这两个消息的附近参数(wParam和lParam)包含的是虚拟键代码和扫描码等信息,而我们经常用的是ASCII码,TranslateMessage可以将WM_KEYDOWN和WM_KEYUP消息组合转换成产生WM_CHAR消息,该消息的wParam包含了字符的ASCII码,并将新的消息投递到调用线程的消息队列中,TranslateMessage函数只是产生了新消息,并没有去修改原有的消息。

 

DispatchMessage

 

该函数分派一个消息到窗口过程,由窗口过程函数对消息进行处理。DispatchMessage实际上是将消息回传给操作系统,由操作系统调用调用窗口过程函数对消息进行响应,如下图所示。

                            

(1) 操作系统接收到应用程序的窗口消息,将消息投递到应用程序的消息队列中。

(2) 应用程序在消息循环中调用GetMessage函数从消息队列中获取出一条一条的消息。

(3)应用程序调用DispatchMessage,将消息回传给操作系统。

(4)操作系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行响应。

原文地址:https://www.cnblogs.com/jinxiang1224/p/8468391.html