【轉】Windows訊息投遞流程:一般視窗訊息投遞(WM_LBUTTONCLICK)

來源:互聯網
上載者:User

標籤:

原文網址: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. };  

 

【轉】Windows訊息投遞流程:一般視窗訊息投遞(WM_LBUTTONCLICK)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.