libIME 架構說明

PCMan edited this page Sep 11, 2013 · 6 revisions
Clone this wiki locally

使用 libIME,可以避開複雜的 TSF,快速建立輸入法

基本架構:

需要 derive 兩個 C++ classes: Ime::Module 和 Ime::TextService

  • Ime::Module 負責管理整個 dll module 的狀態,以及負責向系統 register/unregister 此輸入法
  • Ime::TextService 則為輸入法主要核心的部分

在 Ime::TextService 的 constructor 中,我們會設定幾個東西:

  1. 保留鍵: 透過 addPreservedKey(),向系統註冊保留鍵。當使用者按下註冊的按鍵組合時,會觸發 onPreservedKey()
  2. 語言列按鈕: 用 addLangBarButton() 新增語言列按鈕,並且設定 icon, menu 等等

每次當使用者切換到我們的輸入法時,Ime::TextService::onActivate() 會被呼叫, 此時 libIME 內部會自動初始化 text service,並且自動處理 preserved keys 和 language bar buttons

接下來,當使用者按下任何按鍵時,會依序發生下列事件:

  • 如果這是保留鍵,onPreservedKey() 會被呼叫
  • 如果不是保留鍵,則會先呼叫 filterKeyDown()過濾。如果 filterKeyDown() 判斷輸入法不需要此按鍵,傳回 false,系統會原封不動,把這個按鍵轉發給應用程式
  • 如果 filterKeyDown() 回傳 true,表示我們的輸入法需要這個按鍵,則應用程式不會收到此按鍵訊息。此時 onKeyDown()會被呼叫,輸入法實作者依照 Ime::KeyEvent 和 Ime::KeyState 的內容處理中文輸入
  • 需要取得在按鍵當下,shift key 是否被按下,可以用 keyEvent.isKeyDown(VK_SHIFT) 判斷,而 caps lock 則可用 keyEvent.isKeyToggled(VK_CAPITAL)判斷 (若在無 keyEvent object 的狀況下,可建立 KeyState 物件)
  • 如果此時還沒開始 composition, 需要先 startComposition() 來開啟
  • 如果已有初步的組字結果,呼叫 setCompositionString() 把它顯示出來
  • 如果此時判斷需要開啟選字視窗(candidate window)供使用者選字,則輸入法實作者需要自己提供這個視窗。如果沒有特殊需求,可用 libIME 內建現成的 Ime::CandidateWindow 來實做。適合放置 candidate window 的螢幕位置,可用 selectionRect() 取得目前游標所在螢幕座標,或用 compositionRect() 取得 composition string 之位置和大小
  • 如果組字結束,呼叫 endComposition(),則目前 composition string 會被 commit 輸出

當使用者放開按鍵時,會依序發生下列事件:

  • filterKeyUp() 被呼叫
  • 如果 filterKeyUp() 傳回 true 表示輸入法需要此按鍵,則 onKeyUp() 會被呼叫

當使用者按下語言列按鈕,或任何選單項目,會呼叫 onCommand() 輸入法實作者可在其中處理這些事件

當使用者切換到其他輸入法,或關閉中文輸入法, Ime::TextService::onDeactivate() 會被呼叫,此時進行 cleanup

其他工具:

  • Unicode: utf8ToUtf16() 和 utf16ToUtf8() 函數,可做 utf8/utf16 雙向轉換
  • GUI: 有 Ime::Window, Ime::Dialog, (Ime::PropertyPage + Ime::PropertyDialog)等工具,derive 這些 class,再 override wndProc() 這個 method 來處理各種視窗訊息。