• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            面對現(xiàn)實(shí),超越自己
            逆水行舟,不進(jìn)則退
            posts - 269,comments - 32,trackbacks - 0

            PreTranslateMessage作用和使用方法

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


                    
            MFC消息控制流最具特色的地方是CWnd類的虛擬函數(shù)PreTranslateMessage(),通過重載這個(gè)函數(shù),可以改變MFC的消息控制流程,甚至可以作一個(gè)全新的控制流出來。只有穿過消息隊(duì)列的消息才受PreTranslateMessage()影響,采用SendMessage()或其他類似的方式向窗口直接發(fā)送的而不經(jīng)過消息隊(duì)列的消息根本不會(huì)理睬PreTranslateMessage()的存在。 


                   是否調(diào)用TranslateMessage()DispatchMessage()是由一個(gè)名稱為PreTranslateMessage()函數(shù)的返回值決定的,如果該函數(shù)返回TRUE,則不會(huì)把該消息分發(fā)給窗口函數(shù)處理。
                   傳給PreTranslateMessage()的消息是未經(jīng)翻譯過的消息,它沒有經(jīng)過TranslateMessage()處理??梢栽谠摵瘮?shù)中使用(pMsg->wParam==VK_RETURN)來攔截回車鍵。wParam中存放的是鍵盤上字符的虛擬碼。

            PeekMessage
            GetMessage的區(qū)別:
            GetMessage
            在沒有消息的時(shí)候等待消息,cpu當(dāng)然低
            PeekMessage
            沒有消息的時(shí)候立刻返回,所以cpu占用率高。
            因?yàn)橛螒虿荒芸?/span>windows消息驅(qū)動(dòng),所以要用PeekMessage(); 
                 PretranslateMessage
            的實(shí)現(xiàn),不得不談到MFC消息循環(huán)的實(shí)現(xiàn)。MFC通過CWinApp類中的Pumpmessage函數(shù)實(shí)現(xiàn)消息循環(huán),但是實(shí)際的消息循環(huán)代碼位于CWinThread中,CWinApp只是從CWinThread繼承過來。其簡化后的代碼大概如下: 

             1   BOOL CWinThread::PumpMessage() 
             2   { 
             3   _AFX_THREAD_STATE *pState = AfxGetThreadState(); 
             4    
             5   ::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL)) 
             6    
             7   if (!AfxPreTranslateMessage(&(pState->m_msgCur))) 
             8   { 
             9   ::TranslateMessage(&(pState->m_msgCur)); 
            10   ::DispatchMessage(&(pState->m_msgCur)); 
            11   } 
            12   return TRUE; 
            13   }
                  

                  可以看到,PumpMessage在實(shí)際的TranslateMessageDispatchMessage發(fā)生之前會(huì)調(diào)用AfxPreTranslateMessage,AfxPreTranslateMessage又會(huì)調(diào)用CWnd::WalkPreTranslateTree(雖然也會(huì)調(diào)用其他函數(shù),但是這個(gè)最為關(guān)鍵),其代碼如下:

             1 BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg) 
             2   { 
             3   ASSERT(hWndStop == NULL || ::IsWindow(hWndStop)); 
             4   ASSERT(pMsg != NULL); 
             5    
             6   // walk from the target window up to the hWndStop window checking 
             7   // if any window wants to translate this message 
             8    
             9   for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) 
            10   { 
            11   CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); 
            12   if (pWnd != NULL) 
            13   { 
            14   // target window is a C window 
            15   if (pWnd->PreTranslateMessage(pMsg)) 
            16   return TRUE; // trapped by target window (eg: accelerators) 
            17   } 
            18    
            19   // got to hWndStop window without interest 
            20   if (hWnd == hWndStop) 
            21   break
            22   } 
            23   return FALSE; // no special processing 
            24   } 
                

            可以看到,代碼還是很直接的。從接受到消息的窗口層層往上遍歷,并調(diào)用PretranslateMessage看是否返回TRUE,是則結(jié)束,否則繼續(xù)。
              這里有一個(gè)地方非常關(guān)鍵:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 這一句代碼從當(dāng)前AfxModuleThreadState拿到Permanent句柄表,從而找到hWnd對應(yīng)的CWnd MFCPreTranslateMessageGetMessage(...)函數(shù)的下一級(jí)操作,即GetMessage(...)從消息隊(duì)列中獲取消息后,交由PreTranslateMessage()處理,若其返回FALSE則再交給TranslateMessageDispatchMessage處理(進(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)把來自硬件(鼠標(biāo),鍵盤等消息)和來自應(yīng)用程序的消息 放到一個(gè)系統(tǒng)消息隊(duì)列中去而應(yīng)用程序需要有自己的消息隊(duì)列,也就是線程消息隊(duì)列,每一個(gè)線程有自己的消息隊(duì)列,對于多線程的應(yīng)用程序就有和線程數(shù)目相等的線程消息隊(duì)列.  
              windows
            消息隊(duì)列把得到的消息發(fā)送到線程消息隊(duì)列,線程消息隊(duì)列每次取出一條消息發(fā)送到指定窗口,不斷循環(huán)直到程序退出實(shí)現(xiàn)的.這個(gè)循環(huán)就是靠消息環(huán)(while(GetMessage()) TranslateMessage();DispatchMessage();.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);
             }

             win32 程序中,關(guān)于消息有兩種傳遞方式:

            1.      MFC 消息, MFC 會(huì)把所有的消息一條條放到一個(gè) AFX_MSGMAP_ENTRY 結(jié)構(gòu)中,形成一個(gè)數(shù)組,該數(shù)組存放了所有的消息和與

            它們相關(guān)的參數(shù)。也可以說是放到消息隊(duì)列里去。

            2.      采用 SendMessage() 或其他類似的方式向窗口直接發(fā)送的而不經(jīng)過消息隊(duì)列的消息。


            這兩種方式中只有第一種(穿過消息隊(duì)列的消息)才受 PreTranslateMessage() 影響,

            第二種消息并不會(huì)理睬 PreTranslateMessage() 的存在。

            1)      是否調(diào)用 TranslateMessage() 和 DispatchMessage() 是由一個(gè)名稱為 PreTranslateMessage() 函數(shù)的返回值決定的,如果該函數(shù)返回

             TRUE ,則不會(huì)把該消息分發(fā)給窗口函數(shù)處理。

            2)      傳給 PreTranslateMessage() 的消息是未經(jīng)翻譯過的消息,它沒有經(jīng)過 TranslateMessage() 處理??梢栽谠摵瘮?shù)中使用 

            (pMsg->wParam==VK_RETURN) 來攔截回車鍵。

            3)      在 WindowProc 里不能處理 WM_Char 消息。( WindowProc 函數(shù)見 MFC 消息響應(yīng)機(jī)制一文)

            4)      SetWindowText 會(huì)發(fā)送 WM_Char 給窗口。

            5)      PeekMessage 和 GetMessage 的區(qū)別:

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

            7)      PeekMessage 沒有消息的時(shí)候立刻返回,所以 cpu 占用率高。因?yàn)橛螒虿荒芸?nbsp;windows 消息驅(qū)動(dòng),所以要用 PeekMessage();


            另一篇文章中:

                        在一個(gè) WIN32 程序中, WINDOWS 會(huì)將消息傳遞給相應(yīng)的窗口。但是消息不是立即就被傳遞給相應(yīng)的窗口,而是會(huì)從整個(gè)程序最頂層

            的窗口傳遞到下一級(jí)窗 口,再傳遞到下一級(jí)窗口,直到傳遞給目標(biāo)窗口。在整個(gè)過程中,有些消息,在某些特定的情況下,無法默認(rèn)傳遞到目

            標(biāo)窗口的。比如用戶在 EDIT 控件中按下回 車鍵, CANCEL 鍵等,如果 EDIT 窗口之前有對話框窗口,對話框會(huì)默認(rèn)處理回車消息(即響應(yīng) 

            ONOK 函數(shù),然后關(guān)閉對話框),然后退出消息傳遞。所以 EDIT 會(huì)收不到。要解決這個(gè)問題,可以在 EDIT 窗口之前所有的對話框中重載 

            PreTranslateMessage 函數(shù),然后在函數(shù)內(nèi)加上:

            if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN)     // 如果消息類型為WM_KEYDOWN 并且用戶按下的是回車 
              return FALSE;    // 不翻譯消息,直接將消息傳遞下去。具體可查 MSDN 。注意,這里返回值不能為TRUE , TRUE 的意思是翻譯消息后退出消

            息傳遞,如此一來雖然也能避開對話框默認(rèn)處理,但是會(huì)退出消息傳遞,這樣 EDIT 控件照樣得不到消息。

            如此,就可避開對話框默認(rèn)處理,將消息傳遞下去。注意:只有對話框才會(huì)默認(rèn)處理按下回車,CANCEL 消息,其他控件窗口則不會(huì),所以在其

            他窗口中不必重載 PreTranslateMessage 函數(shù),當(dāng)然如果重載了也不會(huì)錯(cuò)。


            附:關(guān)于 PreTranslateMessage() 函數(shù)的小程序示例:

              1 BOOL CSearchuserDlg::PreTranslateMessage(MSG* pMsg) 
              3 {
              5      if (pMsg->message==WM_KEYDOWN)  // 判斷是否有按鍵按下 
              7      { 
              9            switch (pMsg->wParam) 
             11            { 
             13            case VK_DOWN:     // 表示是方向鍵中的向下的鍵
             15                 //add handle code here
             17                 break ;
             19            case VK_UP:      // 表示是方向鍵中的向上的鍵
             21                 //add handle code here
             23                 break ;
             25            default :
             27                 break ;
             29            }
             31      }
             33 } 
             36 
             37 BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
             38 {
             39      // TODO: Add your specialized code here and/or call the base class 
             41      // 按鍵相應(yīng)
             42      if (pMsg->message == WM_KEYDOWN)
             43      {
             44            if (pMsg->wParam == VK_DOWN)
             45            {
             46                 // 向下鍵按下
             47            }
             48            else if (pMsg->wParam == VK_RIGHT)
             49            {
             50                 // 向右鍵按下
             51            }
             52            else if (pMsg->wParam == VK_LEFT)
             53           {
             54                 // 向左鍵按下
             55            }
             56            else if (pMsg->wParam == VK_UP)
             57            {
             58                 // 向上鍵按下
             59            }
             60            else if (pMsg->wParam == VK_SHIFT)
             61            {
             62                 //VK_LSHIFT 為左 Shift 鍵按下
             63                 //Shift 鍵按下
             64            }
             65            else if (pMsg->wParam == VK_CONTROL)
             66            {
             67                 //Ctrl 鍵按下
             68            }
             69            else if (pMsg->wParam>=VK_NUMPAD0 && pMsg->wParam<=VK_NUMPAD9)
             70            {
             71                 // 小鍵盤數(shù)字鍵按下
             72            }
             73            else if (pMsg->wParam>=0x30 && pMsg->wParam<=0x39)
             74            {
             75                 // 數(shù)字鍵按下 ( 我記得不能使用 VK_0)
             76            }
             77            else if (pMsg->wParam>=0x41 && pMsg->wParam<=0x5A)
             78            {
             79                 // 鍵盤字母鍵按下 ( 我記得不能使用 VK_A)
             80            }
             81            else if (pMsg->wParam == VK_BACK)
             82            {
             83                 // 退格鍵按下
             84            }
             85            else if (pMsg->wParam == VK_DELETE)
             86            {
             87                 // 刪除鍵按下
             88            }
             89            else if (pMsg->wParam == VK_F1)
             90            {
             91                 //F1 鍵按下
             92            }
             93 
             94            //return true;  // 使消息不再進(jìn)行處理
             95      }
             96 
             97      if (pMsg->message == WM_KEYUP)
             98      {
             99            if (pMsg->wParam == VK_SHIFT)
            100            {
            101                 //Shift 鍵彈起
            102            }
            103            else if (pMsg->wParam == VK_CONTROL)
            104            {
            105                 //Ctrl 鍵彈起
            106            }
            107            //return true;  // 使消息不再進(jìn)行處理
            108      }
            109 
            110      return CDialog::PreTranslateMessage(pMsg);
            111 }
            112 
            113 // 同時(shí)按下 ctrl 鍵
            114 BOOL   CDemo_DevStudioView::PreTranslateMessage(MSG*   pMsg)   // 根據(jù)鍵盤上的按鍵對圖形進(jìn)行相應(yīng)的操作  
            116 
            117      if (pMsg->message==256)   //   256 有鍵按下, 46   DEL 鍵  
            118      { 
            119            switch (pMsg->wParam)   
            120            { 
            121                 /// 向左鍵被按下    
            122            case    37
            123                 { 
            124                      // 同時(shí)按下了 CTRL 鍵  
            125                      if (::GetKeyState(VK_CONTROL)       <       0)       
            126                      {       
            127                      } 
            128                 } 
            129            } 
            130      }
            131 }
            posted on 2012-09-05 12:48 王海光 閱讀(1759) 評(píng)論(0)  編輯 收藏 引用 所屬分類: MFC
            国产精品九九久久免费视频 | 久久久国产99久久国产一| 亚洲综合婷婷久久| 久久综合五月丁香久久激情| 99999久久久久久亚洲| 99久久国产热无码精品免费久久久久| 热99re久久国超精品首页| 国产伊人久久| 久久精品亚洲精品国产色婷| 久久精品国产精品亚洲毛片| 国产∨亚洲V天堂无码久久久| 99久久精品免费观看国产| 亚洲Av无码国产情品久久| 7777精品久久久大香线蕉| 99久久婷婷国产综合精品草原 | 亚洲国产成人精品91久久久| 亚洲欧美国产精品专区久久 | 精品久久久噜噜噜久久久| 激情综合色综合久久综合| 久久天天躁狠狠躁夜夜躁2O2O| 国产精品久久久久天天影视| 99久久精品国产一区二区三区| 伊人情人综合成人久久网小说| 久久免费线看线看| 精品国产乱码久久久久久1区2区| 国产一区二区三精品久久久无广告| 亚洲精品乱码久久久久久蜜桃图片| 93精91精品国产综合久久香蕉 | 香港aa三级久久三级| 亚洲va国产va天堂va久久| 久久国产精品免费一区| 国产精品国色综合久久| 久久久久亚洲av成人网人人软件| 国产精品视频久久久| 久久久久无码精品国产| AAA级久久久精品无码区| 国内精品久久九九国产精品| 一级a性色生活片久久无少妇一级婬片免费放 | 99久久婷婷免费国产综合精品| 热久久最新网站获取| 久久久久亚洲精品无码网址|