乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Windows消息機(jī)制的流程及PreTranslateMessage作用和使用方法

       紫殿 2016-01-12

      http://www.cnblogs.com/renyuan/archive/2013/05/31/3110485.html



      Windows消息機(jī)制的流程:

        A. 操作系統(tǒng)接收應(yīng)用程序的窗口消息,將消息投遞到該應(yīng)用程序的消息隊(duì)列中

        B. 應(yīng)用程序在消息循環(huán)中調(diào)用GetMessage函數(shù)從消息隊(duì)列中取出一條一條的消息,取出消息后,應(yīng)用程序可以對(duì)消息進(jìn)行一些預(yù)處理。

        C. 應(yīng)用程序調(diào)用DispatchMessage,將消息回傳給操作系統(tǒng)。

        D. 系統(tǒng)利用WNDCLASS結(jié)構(gòu)體的lpfnWndProc成員保存的窗口過(guò)程函數(shù)的指針調(diào)用窗口過(guò)程,對(duì)消息進(jìn)行處理。

      PreTranslateMessage作用和使用方法

       PreTranslateMessage是消息在送給TranslateMessage函數(shù)之前被調(diào)用的,絕大多數(shù)本窗口的消息都要通過(guò)這里,比較常用,當(dāng)需要在MFC之前處理某些消息時(shí),常常要在這里添加代碼.  

             MFC消息控制流最具特色的地方是CWnd類的虛擬函數(shù)PreTranslateMessage(),通過(guò)重載這個(gè)函數(shù),可以改變MFC的消息控制流程,甚至可以作一個(gè)全新的控制流出來(lái)。只有穿過(guò)消息隊(duì)列的消息才受PreTranslateMessage()影響,采用SendMessage()或其他類似的方式向窗口直接發(fā)送的而不經(jīng)過(guò)消息隊(duì)列的消息根本不會(huì)理睬PreTranslateMessage()的存在。 
       
             是否調(diào)用TranslateMessage()和DispatchMessage()是由一個(gè)名稱為PreTranslateMessage()函數(shù)的返回值決定的,如果該函數(shù)返回TRUE,則不會(huì)把該消息分發(fā)給窗口函數(shù)處理。 
          傳給PreTranslateMessage()的消息是未經(jīng)翻譯過(guò)的消息,它沒有經(jīng)過(guò)TranslateMessage()處理。可以在該函數(shù)中使用(pMsg->wParam==VK_RETURN)來(lái)攔截回車鍵。wParam中存放的是鍵盤上字符的虛擬碼。 

      PeekMessage和GetMessage的區(qū)別: 

      GetMessage在沒有消息的時(shí)候等待消息,cpu當(dāng)然低 

      PeekMessage沒有消息的時(shí)候立刻返回,所以cpu占用率高。 

      因?yàn)橛螒虿荒芸縲indows消息驅(qū)動(dòng),所以要用PeekMessage(); 

           PretranslateMessage的實(shí)現(xiàn),不得不談到MFC消息循環(huán)的實(shí)現(xiàn)。MFC通過(guò)CWinApp類中的Pumpmessage函數(shù)實(shí)現(xiàn)消息循環(huán),但是實(shí)際的消息循環(huán)代碼位于CWinThread中,CWinApp只是從CWinThread繼承過(guò)來(lái)。其簡(jiǎn)化后的代碼大概如下: 
        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在實(shí)際的TranslateMessage和DispatchMessage發(fā)生之前會(huì)調(diào)用AfxPreTranslateMessage,AfxPreTranslateMessage又會(huì)調(diào)用CWnd::WalkPreTranslateTree(雖然也會(huì)調(diào)用其他函數(shù),但是這個(gè)最為關(guān)鍵),其代碼如下: 
        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 
        } 
         
        可以看到,代碼還是很直接的。從接受到消息的窗口層層往上遍歷,并調(diào)用PretranslateMessage看是否返回TRUE,是則結(jié)束,否則繼續(xù)。 
        這里有一個(gè)地方非常關(guān)鍵:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 這一句代碼從當(dāng)前AfxModuleThreadState拿到Permanent句柄表,從而找到hWnd對(duì)應(yīng)的CWnd 


      MFC中PreTranslateMessage是GetMessage(...)函數(shù)的下一級(jí)操作,即GetMessage(...)從消息隊(duì)列中獲取消息后,交由PreTranslateMessage()處理,若其返回FALSE則再交給TranslateMessage和DispatchMessage處理(進(jìn)入WindowProc);  
      如果用SendMessage,   則消息直接交到WindowProc處理,所以GetMessage不會(huì)取得SendMessage的消息,當(dāng)然PreTranslateMessage也就不會(huì)被調(diào)用。   [Page]
      如果用PostMessage,則消息進(jìn)入消息隊(duì)列,由GetMessage取得,PreTranslateMessage就有機(jī)會(huì)進(jìn)行處理。
       
       
      windows消息處理機(jī)制是這樣的:   
            
      首先系統(tǒng)(也就是windows)把來(lái)自硬件(鼠標(biāo),鍵盤等消息)和來(lái)自應(yīng)用程序的消息 放到一個(gè)系統(tǒng)消息隊(duì)列中去
      而應(yīng)用程序需要有自己的消息隊(duì)列,也就是線程消息隊(duì)列,每一個(gè)線程有自己的消息隊(duì)列,對(duì)于多線程的應(yīng)用程序就有和線程數(shù)目相等的線程消息隊(duì)列.   
        windows
      消息隊(duì)列把得到的消息發(fā)送到線程消息隊(duì)列,
      線程消息隊(duì)列每次取出一條消息發(fā)送到指定窗口,不斷循環(huán)直到程序退出.這個(gè)循環(huán)就是靠消息環(huán)(while(GetMessage()) TranslateMessage();DispatchMessage();實(shí)現(xiàn)的.GetMessage()只是從線程消息中取出一條消息,TranslateMessage()virtue key消息轉(zhuǎn)化成character消息,如VK_F1會(huì)轉(zhuǎn)化成WM_HELP,DispatchMessage  則把取出的消息發(fā)送到目的窗口.如果收到WM_CLOSE消息則結(jié)束循環(huán),發(fā)送postqiutmessage(0),處理WM_DESTROY銷毀窗口!
       
       while (GetMessage(&msg, NULL, 0, 0))          //C++ code
       {  
              TranslateMessage(&msg);
              DispatchMessage(&msg);
       }

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多