PreTranslateMessage和TranslateMessage區別

來源:互聯網
上載者:User

 PreTranslateMessage是訊息在送給TranslateMessage函數之前被調用的,絕大多數本視窗的訊息都要通過這裡,比較常用,當需要在MFC之前處理某些訊息時,常常要在這裡添加代碼.  
       

       MFC 訊息控制流程最具特色的地方是CWnd類的虛擬函數PreTranslateMessage(),通過重載這個函數,可以改變MFC的訊息控制流程程,甚至可 以作一個全新的控制流程出來。只有穿過訊息佇列的訊息才受PreTranslateMessage()影響,採用SendMessage()或其他類似的方 式向視窗直接發送的而不經過訊息佇列的訊息根本不會理睬PreTranslateMessage()的存在。  

       是否調用TranslateMessage()和DispatchMessage()是由一個名稱為PreTranslateMessage()函數的傳回值決定的,如果該函數返回TRUE,則不會把該訊息分發給視窗函數處理。 

傳給PreTranslateMessage()的訊息是未經翻譯過的訊息,它沒有經過TranslateMessage()處理。可以在該函數中使用(pMsg->wParam==VK_RETURN)來攔截斷行符號鍵。wParam中存放的是鍵盤上字元的虛擬碼。 

PeekMessage和GetMessage的區別: 

GetMessage在沒有訊息的時候等待訊息,cpu當然低 

PeekMessage沒有訊息的時候立刻返回,所以cpu佔用率高。 

因為遊戲不能靠windows訊息驅動,所以要用PeekMessage(); 

     PretranslateMessage 的實現,不得不談到MFC訊息迴圈的實現。MFC通過CWinApp類中的Pumpmessage函數實現訊息迴圈,但是實際的訊息迴圈代碼位於 CWinThread中,CWinApp只是從CWinThread繼承過來。其簡化後的代碼大概如下: 
  BOOL CWinThread::PumpMessage() 
  { 
  _AFX_THREAD_STATE *pState = AfxGetThreadState(); 
   
  ::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL)) 
   
  if (!AfxPreTranslateMessage(&(pState->m_msgCur))) 
  { 
  ::TranslateMessage(&(pState->m_msgCur)); 
  ::DispatchMessage(&(pState->m_msgCur)); 
  } 
  return TRUE; 
  } 
   可以看到,PumpMessage在實際的TranslateMessage和DispatchMessage發生之前會調用 AfxPreTranslateMessage,AfxPreTranslateMessage又會調用 CWnd::WalkPreTranslateTree(雖然也會調用其他函數,但是這個最為關鍵),其代碼如下: 
  BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg) 
  { 
  ASSERT(hWndStop == NULL || ::IsWindow(hWndStop)); 
  ASSERT(pMsg != NULL); 
   
  // walk from the target window up to the hWndStop window checking 
  // if any window wants to translate this message 
   
  for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) 
  { 
  CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); 
  if (pWnd != NULL) 
  { 
  // target window is a C window 
  if (pWnd->PreTranslateMessage(pMsg)) 
  return TRUE; // trapped by target window (eg: accelerators) 
  } 
   
  // got to hWndStop window without interest 
  if (hWnd == hWndStop) 
  break; 
  } 
  return FALSE; // no special processing 
  } 
   
  可以看到,代碼還是很直接的。從接受到訊息的視窗層層往上遍曆,並調用PretranslateMessage看是否返回TRUE,是則結束,否則繼續。 
  這裡有一個地方非常關鍵:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 這一句代碼從當前AfxModuleThreadState拿到Permanent控制代碼表,從而找到hWnd對應的CWnd 

MFC 中PreTranslateMessage是GetMessage(...)函數的下一級操作,即GetMessage(...)從訊息佇列中擷取訊息 後,交由PreTranslateMessage()處理,若其返回FALSE則再交給TranslateMessage和 DispatchMessage處理(進入WindowProc);   
如果用SendMessage,   則訊息直接交到WindowProc處理,所以GetMessage不會取得SendMessage的訊息,當然PreTranslateMessage也就不會被調用。   [Page]
如果用PostMessage,則訊息進入訊息佇列,由GetMessage取得,PreTranslateMessage就有機會進行處理。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.