MFC框架机制详解
1.1 Windows消息机制要点
1.1.1 窗口过程
每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle), 消息ID(Message ID), 和两个消息参数(wParam, lParam), 当窗口收到消息时系统就会调用此窗口过程来处理消息。(所以叫回调函数)
1.1.2 消息类型
1. 系统定义消息(System-Defined Messages)
在SDK中事先定义好的消息,非用户定义的,其范围在[0x0000, 0x03ff]之间 (1024),
可以分为以下三类:
窗口消息(Windows Message)
与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等。可以是一般的窗口,也可以是Dialog,控件等。所有派生自CWnd 的类才有资格接收标准消息。
第一个消息是:WM_NULL = $0000;
最后一个消息是:WM_DDE_LAST = WM_DDE_FIRST ( 03E0)+8= 03E8=1000;
中间有几个地方并不连续;
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL…
命令消息(Command Message)
与处理用户请求有关, 如单击菜单项或工具栏或控件时, 就会产生命令消息。WM_COMMAND=$0111, LOWORD(wParam)表示菜单项,工具栏按钮或控件的ID。如果是控件, HIWORD(wParam)表示控件消息类型。
所有派生自CCmdTarget 的类都有能力接收WM_COMMAND消息。
控件通知(Notify Message)
控件通知消息, 这是最灵活的消息格式, 其Message, wParam, lParam分别为:WM_NOTIFY= $004E, 控件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-0xFFFF3. 消息队列(Message Queues)
Windows中有两种类型的消息队列
系统消息队列(System Message Queue)
这是一个系统唯一的Queue,设备驱动(mouse, keyboard)会把操作输入转化成消息存在系统队列中,然后系统会把此消息放到目标窗口所在的线程的消息队列(thread-specific message queue)中等待处理
线程消息队列(Thread-specific Message Queue)
每一个GUI线程都会维护这样一个线程消息队列。(这个队列只有在线程调用GDI函数时才会创建,默认不创建)。然后线程消息队列中的消息会被送到相应的窗口过程(WndProc)处理。
注意: 线程消息队列中WM_PAINT,WM_TIMER只有在Queue中没有其他消息的时候才会被处理,WM_PAINT消息还会被合并以提高效率。其他所有消息以先进先出(FIFO)的方式被处理。
4. 队列消息(Queued Messages)和非队列消息(Non-Queued Messages)
队列消息(Queued Messages)
消息会先保存在消息队列中,消息循环会从此队列中取消息并分发到各窗口处理
如鼠标,键盘消息。非队列消息(NonQueued Messages)
消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理
如:WM_ACTIVATE, WM_SETFOCUS,
WM_SETCURSOR, WM_WINDOWPOSCHANGED注意: postMessage发送的消息是队列消息,它会把消息Post到消息队列中; SendMessage发送的消息是非队列消息, 被直接送到窗口过程处理
5. PostMessage(PostThreadMessage), SendMessage
PostMessage:把消息放到指定窗口所在的线程消息队列中后立即返回。 PostThreadMessage:把消息放到指定线程的消息队列中后立即返回。
SendMessage:直接把消息送到窗口过程处理, 处理完了才返回。6. GetMessage, PeekMessage
PeekMessage会立即返回 可以保留消息
GetMessage在有消息时返回 会删除消息
7. TranslateMessage, TranslateAccelerator
TranslateMessage: 把一个virtual-key消息转化成字符消息(character message),并放到当前线程的消息队列中,消息循环下一次取出处理。
TranslateAccelerator: 将快捷键对应到相应的菜单命令。它会把WM_KEYDOWN 或 WM_SYSKEYDOWN转化成快捷键表中相应的WM_COMMAND 或WM_SYSCOMMAND消息, 然后把转化后的 WM_COMMAND或WM_SYSCOMMAND直