• 【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)


    原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182646

    本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数,来解释一般窗口消息的投递流程。 基于VS 2005

    [cpp] view plaincopy
     
    1. BEGIN_MESSAGE_MAP(CMyView, CView)  
    2.     ON_WM_LBUTTONDBLCLK()  
    3. END_MESSAGE_MAP()  
    4. // ON_WM_LBUTTONDBLCLK宏展开  
    5. #define ON_WM_LBUTTONDBLCLK() /  
    6. { WM_LBUTTONDBLCLK, 0, 0, 0, AfxSig_vwp, /  
    7.     (AFX_PMSG)(AFX_PMSGW) /  
    8.     (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > ( &ThisClass :: OnLButtonDblClk)) },  

    从上面的代码可以看出WM_LBUTTONCLICK消息的类型标签是AfxSig_vwp, 在afxmsg_.h中有一个枚举类型AfxSig,消息标签主要用于区分消息处理函数的类型。该类型中定义了AfxSig_vwp的值:

    [cpp] view plaincopy
     
    1. enum AfxSig  
    2. {  
    3.     //...  
    4.     AfxSig_vWp = AfxSig_v_W_p  
    5.     //...  
    6. }  

    在AfxWndProc中,将消息中的句柄映射成窗口类指针,这个指针指向CMyView。AfxWndProc调用AfxCallWndProc,AfxCallWndProc调用CWnd::WindowProc,CWnd::WindowProc调用CWnd::OnWndMsg,CWnd::OnWndMsg完成对消息的处理。

    [cpp] view plaincopy
     
    1. // wincore.cpp 1746  
    2. BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)  
    3. {  
    4.     // ...  
    5.     // GetMessageMap是个虚函数,因为当前指针是指向CMyView,所以取到的是CMyView的消息映射表  
    6.     const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();     
    7.     UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1);  
    8.     winMsgLock.Lock(CRIT_WINMSGCACHE);  
    9.     // 全局消息散列缓存,查找缓存  
    10.     AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];  
    11.     const AFX_MSGMAP_ENTRY* lpEntry;  
    12.     if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)  
    13.     {  
    14.         // cache hit  
    15.         lpEntry = pMsgCache->lpEntry;  
    16.         winMsgLock.Unlock();  
    17.         if (lpEntry == NULL)  
    18.             return FALSE;  
    19.         // cache hit, and it needs to be handled  
    20.         if (message < 0xC000)  
    21.             goto LDispatch;     // 系统消息?  
    22.         else  
    23.             goto LDispatchRegistered;       // 已注册消息?  
    24.     }  
    25.     else  
    26.     {  
    27.         // not in cache, look for it  
    28.         pMsgCache->nMsg = message;  
    29.         pMsgCache->pMessageMap = pMessageMap;  
    30.         for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL;  
    31.             pMessageMap = (*pMessageMap->pfnGetBaseMap)())  
    32.         {  
    33.             // Note: catch not so common but fatal mistake!!  
    34.             //      BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)  
    35.             ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());  
    36.             if (message < 0xC000)  
    37.             {  
    38.                 // constant window message  
    39.                 if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,  
    40.                     message, 0, 0)) != NULL)  
    41.                 {  
    42.                     pMsgCache->lpEntry = lpEntry;  
    43.                     winMsgLock.Unlock();  
    44.                     goto LDispatch;  
    45.                 }  
    46.             }  
    47.             else  
    48.             {  
    49.                 // registered windows message  
    50.                 lpEntry = pMessageMap->lpEntries;  
    51.                 while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)  
    52.                 {  
    53.                     UINT* pnID = (UINT*)(lpEntry->nSig);  
    54.                     ASSERT(*pnID >= 0xC000 || *pnID == 0);  
    55.                     // must be successfully registered  
    56.                     if (*pnID == message)  
    57.                     {  
    58.                         pMsgCache->lpEntry = lpEntry;  
    59.                         winMsgLock.Unlock();  
    60.                         goto LDispatchRegistered;  
    61.                     }  
    62.                     lpEntry++;      // keep looking past this one  
    63.                 }  
    64.             }  
    65.         }  
    66.         pMsgCache->lpEntry = NULL;  
    67.         winMsgLock.Unlock();  
    68.         return FALSE;  
    69.     }  
    70.     // ...  
    71. LDispatch:  
    72.     mmf.pfn = lpEntry->pfn;  
    73.     switch (lpEntry->nSig)  
    74.     {  
    75.         //...  
    76.     case AfxSig_v_u_p:      // 消息标签  
    77.         {  
    78.             CPoint point(lParam);  
    79.             (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);  
    80.         }  
    81.         break;  
    82.         //...  
    83.     }  
    84.     //...  
    85. LDispatchRegistered:    // for registered windows messages  
    86.     ASSERT(message >= 0xC000);  
    87.     ASSERT(sizeof(mmf) == sizeof(mmf.pfn));  
    88.     mmf.pfn = lpEntry->pfn;  
    89.     lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);  
    90. }  
    91. // 消息处理函数类型枚举  
    92. union MessageMapFunctions  
    93. {  
    94.     AFX_PMSG pfn;   // generic member function pointer  
    95.     // ...  
    96.     LRESULT (AFX_MSG_CALL CWnd::*pfn_l_w_l)(WPARAM, LPARAM);  
    97. };  
  • 相关阅读:
    Python中的时间
    Python + Selenium 自动化环境搭建过程
    HTML手写课程表,练基础
    temp2
    Jenkins配置文件
    Jenkins安装Slave节点
    Jenkins管理插件
    常见的linux上的服务重启脚本
    测试感慨
    docker的安装
  • 原文地址:https://www.cnblogs.com/wi100sh/p/4210173.html
Copyright © 2020-2023  润新知