简析Windows消息机制

Windows消息机制

窗口程序特征
一个Windows上的窗口程序,包含外层的窗口,客户区,菜单栏,标题栏以及按钮,编辑框等!而窗口,控件以及音频,视频,图片等文件统称为资源文件(Resource.h),每个资源文件都对应一个句柄,通过句柄我们可以操控该资源文件

消息机制
Windows窗口程序的运行全靠消息驱动,那什么是消息呢?

消息,从字面理解就是要传递给对方的某个东西, 在Windows上我们的任何行为比如单击鼠标,双击鼠标,输入文字都会产生一条对应的消息

注意:消息也称为事件

谁会最先接收到这个消息呢?

操作系统

谁会去处理这个消息呢?

操作系统虽然最先接收到消息,但是它不会立马处理,它会把这条消息先放到系统消息队列中,再根据句柄等标识将其拷贝到对应的应用程序消息队列中。然后该应用程序的消息循环会不断检索自己的消息队列,并使用回调函数处理每一条消息

注意:当应用程序第一次调用GDI函数时系统才给程序创建一个应用程序消息队列,也称为线程消息队列

操作系统是如何知道消息是由哪一个程序产生的呢?

typedef struct tagMSG{
    HWND hwnd; //接收该消息的窗口句柄
    UINT message; //消息常量标识符,也就是消息号
    WPARAM wParam; //附加信息
    LPARAM lParam; //附加信息
    DWORD time; //当前时间
    POINT pt; //鼠标座标
}MSG;
就是由上面的 MSG 结构体中的窗口句柄决定的,并且 message 变量标识该消息的类型,具体如下:

WM_NULL---0x0000 空消息
0x0001----0x0087 窗口消息
0x00A0----0x00A9 非客户区消息
0x0100----0x0108 键盘消息
0x0111----0x0126 菜单消息
0x0132----0x0138 颜色控制消息
0x0200----0x020A 鼠标消息
0x0211----0x0213 菜单循环消息
0x0220----0x0230 多文档消息
0x03E0----0x03E8 DDE消息
0x0400----0x7FFF WM_USER自定义消息

由于上面这些数值不容易记忆,所以Windows就定义了很多的宏来标识这些消息,比如:鼠标左键按下消息是WM_LBUTTONDOWN,键盘按下消息是WM_KEYDOWN

发送消息
发送消息的函数有SendMessage,SendMessageCallback,SendNotifyMessage,SendMessageTimeout
寄送消息的函数主要有PostMessage,PostThreadMessage,PostQuitMessage
广播消息的函数有BroadcastSystemMessage,BroadcastSystemMessageEx

发送和寄送最大的区别就是:发送的消息不会被放到应用程序消息队列中,寄送的消息会被放到应用程序消息队列中,导致SendMessage必须等消息处理后才返回,PostMessage将消息放到消息队列后立马返回

WM_PAINT
WM_PAINT 消息表示绘制窗口的客户区,窗口经常会收到这个消息,第一条 WM_PAINT 通常发生在 WinMain 中调用 UpdateWindow 时。WM_PAINT 消息在哪些情况下会产生呢?

该窗口的某些部分被遮挡
该窗口的大小被调整
客户区的滚动条滚动

注意:窗口类的 style 字段为 CS_HREDRAW 和 CS_VREDRAW,才能重绘

WM_PAINT 是个特殊的消息,它会合并多个 WM_PAINT,目的是方便将多个无效区域合并成一个大的无效区域以及减少刷新窗口的次数。具体实现:等到应用消息队列为空时才发送WM_PAINT消息

WM_PAINT 的具体处理流程:

  • BeginPaint 获取 DC 设备环境句柄(HDC hdc = BeginPaint(hwnd,&paintstruct))
  • GetClientRect 获取客户区矩形区域(GetClientRect(hwnd,&rect))
  • DrawText 重新显示
  • EndPaint 释放设备上下文句柄(EndPaint(hwnd,&paintstruct))

注意:BeginPaint的一个作用就是把Update Region置为空

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章