日期:2014-05-16  浏览次数:20804 次

Windows消息机制(1):消息简介

事件驱动(event drive)

事件产生消息,应用程序产生消息

在dos系统上的操作比较好理解,敲入一条命令然后执行一系列动作.输入一条命令你就把它类比成输入一个函数名然后调用(有时可能需要参数).而在windows系统上主要是一些图形操作界面.你拿个鼠标在图形哪个区域点一下之后会发生啥事呢? 首先你猜想会不会是在图标上点下也就是去调用一个函数来做些啥操作了啊.实际上本质上来说确实是这样,只不过中间还有些比较复杂的过程.

当我们用鼠标或键盘等做些啥操作时,我们把这些操作叫做事件(event).鼠标键盘是硬件的操作,我们知道应用程序是不会直接和硬件打交道的,只是操作系统去和硬件打交道,然后应用程序只和操作系统去打交道. 当操作系统捕捉到那些事件后会产生对应的消息(message).除此之外,程序还能在代码里直接产生消息.我们知道会不停的发生很多操作,产生很多消息,但是自然一个个的来慢慢处理.于是有所谓的消息队列.

 

消息队列(message queue)

系统消息队列,线程消息队列

队列我们学数据结构时知道,一个先进先出的线性结构.

1)系统消息队列(system message queue)

 所有硬件事件产生的消息都会被操作系统捕获并保存在系统消息队列中.然后操作系统会把这些消息发送到对应的线程消息队列中.

2)线程消息队列(thread-specific message queue)

  我们创建一个窗口时表面上没看到有啥线程,实际上后台的操作是先创建一个UI线程,然后该线程再创建窗口相关内容.每个UI线程都对应有一个线程消息队列.

  而我们自己显式创建一个线程时,如果线程中有用到界面相关的任务(检查其消息队列或者创建一个窗口).那么这个线程我们也当成UI线程,也给它添加个线程消息队列.

  线程消息队列除了接受系统消息队列发送来的消息外,还接受程序中生成的消息,比如通过PostMessage发来的消息.(注意:通过SendMessage发送的消息就不发到线程消息队列   去了,而是直接发给窗口过程去处理了)

 

排队消息与非排队消息

上面讲的系统消息队列和线程消息队列中的消息自然就是所谓的排队消息,顾名思义,在队列中自然要排队去被处理嘛.而像SendMessage产生的消息直接发给窗口过程了,不用排队了,所以叫非排队消息.

 

消息的定义

前面讲了很久的消息了,你可能会问消息这名也太虚了点,它到底长啥样啊,实际上的它就是一个结构体罢了.

typedef struct tagMsg
{
HWND hwnd;
//接受该消息的窗口句柄,一个消息被发到中个线程消息队列或者直接发到哪个窗口过程就由它确定的.
UINT message; //消息常量标识符,比如WM_CREATE
WPARAM wParam; //32位消息的特定附加信息,确切含义依赖于消息值
LPARAM lParam; //32位消息的特定附加信息,确切含义依赖于消息值
DWORD time; //消息创建时的时间
POINT pt; //消息创建时的鼠标/光标在屏幕坐标系中的位置
}
MSG

其中

wParam包含有键盘,鼠标信息,比如
            wParam & MK_LBUTTON判断左键按下
            wParam&MK_SHIFT判断Shift键按下
lParam包含有屏幕坐标信息
           LOWORD(lParam) //x轴
           HIWORD(lParam) //y轴坐标

 

回调函数的定义是LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

函数参数刚好就是MSG前面4个成员变量.