MFC消息机制
一、消息的分类
1、 队列消息、非队列消息
l 队列消息:
windows为每个应用程序都建立一个消息队列,那么通过消息队列,进行传送的消息都属于队列消息;一般来说,由鼠标、键盘产生的消息都属于队列消息。(为什么呢?想想,鼠标、键盘事件都是由系统捕获的,系统捕获后要传递给应用程序,就一定的通过消息队列);
l 非队列消息:
除了队列消息,剩下的自然而然就是非队列消息了;
u 队列消息是通过PostMessage()的方式投递消息的,这样的消息发送也叫“寄送”,该函数寄送消息即可返回,不需要等待程序处理结果;
u 非队列消息是通过SendMessage()的方式进行的,这样的消息发送叫“发送”;消息不需要进入窗口的消息队列,
然而不管是队列消息,还是非队列消息,消息处理的起点都是AfxWndProc。不同的是队列消息,是操作系统把消息投放到消息队列,应用程序空闲是,通过一个消息循环,搜索消息队列,不停的从消息队列抓取消息,并处理。大致流程是:CwinThread->PumpMessage->CWnd->PreTranslateMessage->…………..->USER32内核->AfxWndProcBase->AfxWndProc->…….(继续处理)
而非队列消息呢(即通过SendMessage方式发送的消息)?它是直接进入了USER32内核,然后处理的流程和队列消息一样了。
注意,不管是队列消息,还是非队列消息,都是从USER32内核开始,转到了AfxWndProcBase(有时候不经过这里),再到AfxWndProc,所以可以认为AfxWndProc是消息传递与处理的起点!
补充一点儿:按理说,从USER32出来后,不管是队列消息,还是非队列消息,应该由Windosw系统发往各个窗口的消息处理函数(这个处理函数是DefWindowProc,这是很直觉的想法,而且传统的SDK程序确实是这样的,但是MFC程序比传统的SDK多了document/view,如果如果某个消息是做文档处理,那么就让这个消息直接流到document中去不是更好吗?所以才有了MFC命令传递机制、MFC消息映射的出现),但是为什么都统一到了AfxWndProc这里呢?这里用到了钩子技术。(关于这一段儿描述的,不管是“深入浅出MFC”、“MFC逆向分析”、“精通MFC”都由介绍,但是都不是很清楚,需要再仔细揣摩。而且由于MFC版本的不同,实际的函数流程也可能和资料描述的不同)[微软用户1]
2、 命令消息、通知消息、一般消息
下面以表格来分析这几类消息:
|
形式 |
来源 |
谁能处理? |
|
命令消息 |
WM_Command |
菜单、工具栏 |
凡派生自CcmdTarget的类,都可以 |
|
通知消息 |
WM_Notify,也是以WM_Command形式出现 |
子控件传给父控件的 |
|
|
一般消息(又叫标准消息、窗口消息) |
WM_(任意),比如WM_Create、WM_Move等等 |
|
派生自CWnd的类 |
|
然而,看一下MFC一些基类的继承关系,如下图:
Cobject
|
CCmdTarget
|
|----CwinThread---CWinApp---CMyWinApp
|
|----CWnd----
| |----CView
| |----CFrameWnd
|
|----Cdocument----CmyDoc
看上图的继承关系,可以这么说,
a) 凡是派生自CWnd的类,可以拦截并处理任何Windows消息,不管是WM_Command,还是WM_Notify,还是其它什么WM_Create、WM_Move等消息;
b) 而与窗口无关的CwinApp类、Cdocument类,因为继承自CcmdTarget,只能处理WM_Command消息;因为没有继承自CWnd,不能处理一般消息。
3、 消息的处理流程
好了,有了前面1、2小节的基础,我们接下来来看消息的处理流程:
[微软用户1]这一块儿似懂非懂,需要继续研究