MFC消息处理流程概述

Win32下的消息流程清晰明了,但在MFC下,由于封装的缘故,隐藏的有点深,对一般的开发人员而言,就不甚明了喽。本文试图粗略展示出MFC下消息处理的基本流程。

一、先看一下Win32下的消息处理流程

    每一个线程都对应有一个消息队列,利用API函数GetMessage从消息队列中获取消息,然后利用TranslateMessage翻译消息(主要是一些键盘消息),再利用DispatchMessage将消息分发给对应的窗口过程函数处理。

    一般我们在WinMain函数中利用如下代码来处理消息:

  1. while (GetMessage(&msg, NULL, 0, 0)) 
  2.     TranslateMessage(&msg); 
  3.     DispatchMessage(&msg); 
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

    很显然,整个消息循环很清楚。

二、MFC下的消息处理流程

1、MFC下的消息处理流程由thrdcore.cpp中的AfxInternalPumpMessage开始:

  1. BOOL AFXAPI AfxInternalPumpMessage() 
  2.     MSG msg; 
  3.     ::GetMessage(&msg, NULL, NULL, NULL); 
  4.     if (!AfxPreTranslateMessage(&msg)) 
  5.     { 
  6.         ::TranslateMessage(&msg); 
  7. ::DispatchMessage(&msg); 
  8.     } 
  9.     return TRUE; 
    BOOL AFXAPI AfxInternalPumpMessage()
    {
        MSG msg;
        ::GetMessage(&msg, NULL, NULL, NULL);
        if (!AfxPreTranslateMessage(&msg))
        {
            ::TranslateMessage(&msg);
	    ::DispatchMessage(&msg);
        }
        return TRUE;
    }

注:以上代码为示意代码,具体请参照MFC的源码。

    很显然,其消息处理流程也类似<一>中Win32下的消息处理,只不过在调用TranslateMessage、DispatchMessage处理消息前增加了类似过滤的函数AfxPreTranslateMessage。该函数会调用CWnd类的PreTranslateMessage函数,函数返回True则消息将不会被处理。我们经常会通过重载CWnd类的PreTranslateMessage来改变MFC的消息控制流程。
2、窗口过程函数
    通过调用DispatchMessage将消息分发给了具体的窗口过程函数处理。MFC下的所有窗口都拥有公用的窗口过程函数AfxWndProc。该函数的示意代码如下:

  1. LRESULT CALLBACK AfxWndProc(HWND hWnd,UINT nMsg, WPARAM wParam,LPARAM lParam) 
  2.         CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);  //从HWND获取对应的CWnd* 
  3.         if (pWnd == NULL || pWnd->m_hWnd != hWnd) 
  4.                 return ::DefWindowProc(hWnd, nMsg, wParam, lParam); 
  5.         else     
  6.                 return pWnd->WindowProc(nMsg, wParam, lParam); 
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
        CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);  //从HWND获取对应的CWnd*
        if (pWnd == NULL || pWnd->m_hWnd != hWnd)
                return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
        else	
                return pWnd->WindowProc(nMsg, wParam, lParam);
}

    很显然,调用了CWnd类的虚函数virtual CWnd::WindowProc处理。

  1. LRESULT CWnd::WindowProc(UINT message,WPARAM wParam, LPARAM lParam) 
  2.     // OnWndMsg does most of the work, except for DefWindowProc call 
  3.     LRESULT lResult = 0; 
  4.     if (!OnWndMsg(message, wParam, lParam, &lResult)) 
  5.         lResult = DefWindowProc(message, wParam, lParam); 
  6.     return lResult; 
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	// OnWndMsg does most of the work, except for DefWindowProc call
	LRESULT lResult = 0;
	if (!OnWndMsg(message, wParam, lParam, &lResult))
		lResult = DefWindowProc(message, wParam, lParam);
	return lResult;
}

    WindowProc函数又调用了CWnd类的虚函数virtual CWnd::OnWndMsg处理。

  1. BOOL CWnd::OnWndMsg(UINT message,WPARAM wParam, LPARAM lParam,LRESULT* pResult) 
  2.     LRESULT lResult = 0; 
  3.     union MessageMapFunctions mmf; 
  4.     mmf.pfn = 0; 
  5.     CInternalGlobalLock winMsgLock; 
  6.     // special case for commands 
  7.     if (message == WM_COMMAND) 
  8.     { 
  9.         if (OnCommand(wParam, lParam)) 
  10.         { 
  11.             lResult = 1; 
  12.             goto LReturnTrue; 
  13.         } 
  14.         return FALSE; 
  15.     } 
  16.  
  17.     // special case for notifies 
  18.     if (message == WM_NOTIFY) 
  19.     { 
  20.         NMHDR* pNMHDR = (NMHDR*)lParam; 
  21.         if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult)) 
  22.             goto LReturnTrue; 
  23.         return FALSE; 
  24.     } 
  25.      
  26.     ...... 
  27.  
  28.     return TRUE; 
BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	LRESULT lResult = 0;
	union MessageMapFunctions mmf;
	mmf.pfn = 0;
	CInternalGlobalLock winMsgLock;
	// special case for commands
	if (message == WM_COMMAND)
	{
		if (OnCommand(wParam, lParam))
		{
			lResult = 1;
			goto LReturnTrue;
		}
		return FALSE;
	}

	// special case for notifies
	if (message == WM_NOTIFY)
	{
		NMHDR* pNMHDR = (NMHDR*)lParam;
		if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
			goto LReturnTrue;
		return FALSE;
	}
	
	......

	return TRUE;
}
    在OnWndMsg函数中会根据具体的消息类型,在MFC的消息映射表中找到对应的函数处理。
    以上就是MFC处理消息的大致流程。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值