zoukankan      html  css  js  c++  java
  • MFC消息处理流程概述 .

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

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

        每一个线程都对应有一个消息队列,利用API函数GetMessage从消息队列中获取消息,然后利用TranslateMessage翻译消息(主要是一些键盘消息),再利用DispatchMessage将消息分发给对应的窗口过程函数处理。
        一般我们在WinMain函数中利用如下代码来处理消息:
    1. while (GetMessage(&msg, NULL, 0, 0))  
    2. {  
    3.     TranslateMessage(&msg);  
    4.     DispatchMessage(&msg);  
    5. }  
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
        很显然,整个消息循环很清楚。

    二、MFC下的消息处理流程

    1、MFC下的消息处理流程由thrdcore.cpp中的AfxInternalPumpMessage开始:
    1. BOOL AFXAPI AfxInternalPumpMessage()  
    2. {  
    3.     MSG msg;  
    4.     ::GetMessage(&msg, NULL, NULL, NULL);  
    5.     if (!AfxPreTranslateMessage(&msg))  
    6.     {  
    7.         ::TranslateMessage(&msg);  
    8.  ::DispatchMessage(&msg);  
    9.     }  
    10.     return TRUE;  
    11. }  
        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. {  
    3.         CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);  //从HWND获取对应的CWnd*   
    4.         if (pWnd == NULL || pWnd->m_hWnd != hWnd)  
    5.                 return ::DefWindowProc(hWnd, nMsg, wParam, lParam);  
    6.         else      
    7.                 return pWnd->WindowProc(nMsg, wParam, lParam);  
    8. }  
    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. {  
    3.     // OnWndMsg does most of the work, except for DefWindowProc call   
    4.     LRESULT lResult = 0;  
    5.     if (!OnWndMsg(message, wParam, lParam, &lResult))  
    6.         lResult = DefWindowProc(message, wParam, lParam);  
    7.     return lResult;  
    8. }  
    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. {  
    3.     LRESULT lResult = 0;  
    4.     union MessageMapFunctions mmf;  
    5.     mmf.pfn = 0;  
    6.     CInternalGlobalLock winMsgLock;  
    7.     // special case for commands   
    8.     if (message == WM_COMMAND)  
    9.     {  
    10.         if (OnCommand(wParam, lParam))  
    11.         {  
    12.             lResult = 1;  
    13.             goto LReturnTrue;  
    14.         }  
    15.         return FALSE;  
    16.     }  
    17.   
    18.     // special case for notifies   
    19.     if (message == WM_NOTIFY)  
    20.     {  
    21.         NMHDR* pNMHDR = (NMHDR*)lParam;  
    22.         if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))  
    23.             goto LReturnTrue;  
    24.         return FALSE;  
    25.     }  
    26.       
    27.     ......  
    28.   
    29.     return TRUE;  
    30. }  
    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处理消息的大致流程。


    from:http://blog.csdn.net/wangyao1052/article/details/8045017
  • 相关阅读:
    cors
    js 离开页面
    移动端 touch
    eclipse
    java获取classpath以外的路径
    Javascript类型转换的规则
    myeclipse开发安装C++
    MyEclipse10中配置开发Python所需要的PyDev 绝对靠谱 不忽悠!
    POI生成EXCEL,公式不自动执行的有关问题
    POI中设置Excel单元格格式样式(居中,字体,边框等)
  • 原文地址:https://www.cnblogs.com/lidabo/p/2804239.html
Copyright © 2011-2022 走看看