so true

心怀未来,开创未来!
随笔 - 160, 文章 - 0, 评论 - 40, 引用 - 0
数据加载中……

MFC的消息映射机制

=================================================================================================
MFC将消息分为以下三种类型:
(1)标准消息:除WM_COMMAND之外,所有以WM_开头的消息,从CWnd派生的类,都可以接收到这类消息。
(2)命令消息:来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。从CCmdTarget派生的类,都可以接收到这类消息。
(3)通告消息:由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现。从CCmdTarget派生的类,都可以接收到这类消息。

某个窗口产生一个消息,该消息中的第一个参数就是与这个窗口有关的句柄,由于VC++系统在后台维护了一个句柄和指针的映射关系,因此就可以从这个句柄找到对应的指针,然后将指针传递给基类,消息循环的最终结果都会归结为调用基类(窗口类的基类也就是CWnd类)中的WindowProc函数,下面详细的分析了MFC对消息的处理过程:
MFC对于各类消息都是先交由一个“Afx(即应用程序框架函数)”LRESULT CALLBACK AfxWndProc<for all CWnd's and derived classes>来处理;
然后再调用LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0)<Official way to send message to a CWnd>;
然后再调用LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)<main WindowProc implementation>;
然后再调用BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);在OnWndMsg函数中会针对不同的消息类型进行不同的处理,对于命令消息它会交由BOOL OnCommand(WPARAM wParam, LPARAM lParam)来处理;对于通告消息,会交由BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)来处理;需要说明的一点是不论是命令消息还是通告消息,最终都会调用OnCmdMsg函数。如果消息不是命令消息或通告消息,即为标准消息,则会最终到一个switch结构中去寻找,如果在OnWndMsg中未能响应消息,则交由默认的消息处理函数LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)<Default CWnd implementation>。
在OnWndMsg函数中的case结构中有很多类似于这样的语句:lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);根据多态性,这里面的this指针往往都是指向基类的,例如CMainFrame或CXXXView类等的对象,这里面的mmf.pfn_is是一个指向函数的指针,因此执行这句话调用消息处理的入口就会遵循先到子类中查找是否存在这样的消息处理函数,如果子类没有,才会上溯到基类中去寻找。
=================================================================================================
自定义消息:#define UM_XXXX WM_USER+X;声明消息响应函数原型afx_msg void OnXXXX();添加消息映射ON_MESSAGE(UM_XXXX,OnXXXX);编写消息响应函数代码;使用SendMessage或者PostMessage函数发送消息。

GetMessage会等待消息处理完毕后再取出下一条消息;PeekMessage只会窥视一下即将取出的下一条消息,而不会做任何与消息处理有关的工作。

CWnd::SendMessage会发送消息,并等待消息返回,在程序执行过程中使用该函数,就相当于把消息响应函数的函数体插放到当前程序体中;CWnd::PostMessage会发送消息,但是不会等待消息处理完成后才返回,这个函数会立刻返回,它只是在消息队列的头部放置了一个新的消息,至于这个消息多会儿被响应就是系统底层消息循环的事情了。
=================================================================================================
这里要提到的这个观点太过于经典了,因此一定要好好领会,永远不能忘记。

MFC的消息相应是通过将产生的消息放置到一个消息队列中,然后由系统不停的从队列的头部取出消息进行响应和执行,由于消息响应在一个时刻只能响应一个消息,而不能同时响应若干个消息,因此只有等待当前的消息处理完成后才能够进行下一个消息的响应,因此如果我们希望在响应完一个消息之后(也就是在程序中表现为执行完一个消息响应函数的函数体之后)再去做另外一件工作,那就可以在当前的消息响应函数中发送一个消息,在这个发送出去的消息的响应函数中去做那些工作就可以了。而这个发送的消息可以是我们自定义的消息。
=================================================================================================

posted on 2008-02-23 19:14 so true 阅读(512) 评论(0)  编辑  收藏 所属分类: C&C++


只有注册用户登录后才能发表评论。


网站导航: