1. 程式人生 > >切換輸入法導致程式宕機的解決辦法

切換輸入法導致程式宕機的解決辦法

轉自:https://blog.csdn.net/chenlycly/article/details/7345040

 近日在開發類似QQ螢幕截圖過程中,發現在輸入文字時切換輸入法(Ctrl+Shift)時,會導致程式出現“卡死”現象。為了方便程式碼重用,螢幕截圖模組是以動態庫方式封裝起來的。出現“卡死”現象後,只能通過工作管理員強制殺掉對應的程序才能退出程式。於是,上網搜尋了相關話題,發現原因通常是某種輸入法如紫光或搜狗輸入法導致了程式宕機,也可能是某種軟體與輸入法衝突導致宕機。

        通過程式碼註釋最終找到了問題所在,可能在程式呼叫的某個dll庫中截獲了輸入法訊息,但是沒有將輸入法訊息釋放出來給介面執行緒處理導致介面掛死。

        那麼輸入法具體機制又是怎麼的呢?Windows的輸入法其實就是一個系統目錄下的IME檔案,IME檔案其實就是一個特殊的DLL,它必須具有輸入法程式所規定的那些介面。輸入法是由輸入法管理器(imm32.dll)控制的,輸入法管理器又是由user32.dll控制的。當在應用程式中通過滑鼠或者鍵盤(user32.dll捕獲這些事件)啟用某個輸入法時,輸入法管理器就會在那個應用程式的程序中載入對應的IME檔案,載入IME檔案跟載入普通的DLL並沒有本質區別,所以,我們可以認為,輸入法其實就是載入到應用程式中的一個DLL檔案。在切換輸入法之前輸入法檔案並不會被載入,切換輸入法之後OS向系統中的獲得焦點的視窗POST一條WM_INPUTLANGCHANGEREQUEST

訊息,該訊息可以在視窗的後臺啟用輸入法,如果某個視窗自動啟用失敗,就需要在那個視窗中手工切換輸入法,這樣才能將輸入法檔案載入進去。微軟對傳送WM_INPUTLANGCHANGEREQUEST訊息時機的解釋是:當用戶選擇某種輸入語言,或輸入語言的熱鍵改變。

        系統傳送WM_INPUTLANGCHANGEREQUEST訊息時會附帶引數lParam,lParam代表切換後的輸入法標識。此標識可以被ActivateKeyboardLayout作為引數使用,ActivateKeyboardLayout用於啟用對應輸入法。程式碼如下:

  1. HKL hkl = (HKL)pMsg->lParam;
  2. ActivateKeyboardLayout(hkl, KLF_REPLACELANG);//啟用對應輸入法

       主執行緒啟用對應輸入法之後,需要返回True,不讓其它執行緒處理輸入法訊息,避免出現卡死現象。具體的解決辦法:只需在你的主執行緒訊息入口新增如下程式碼即可:

  1. BOOL CXXXApp::PreTranslateMessage(MSG* pMsg)
  2. {
  3. // 解決切換輸入法時,導致宕機的問題。
  4. if ( pMsg->message == WM_INPUTLANGCHANGEREQUEST)
  5. {
  6. HKL hkl = (HKL)pMsg->lParam;
  7. ActivateKeyboardLayout(hkl, KLF_REPLACELANG);//啟用對應輸入法
  8. // 直接返回,不要呼叫預設的輸入法處理;否則會導致宕機
  9. return TRUE;
  10. }
  11. }