2011年8月5日 星期五

Windows CE 輸入法...

先寫在這做筆記, 我不確定完全正確...
在做 windows CE 的東西時, 只要碰上非英語語系界面時都會碰上這個問題:

ERROR: C:\WINCE600\public\common\oak\drivers\keybd\LAYMGR\.\LayMgr.cpp line 1600: MapVirtualKey: No input language installed
ERROR: C:\WINCE600\public\common\oak\drivers\keybd\LAYMGR\.\LayMgr.cpp line 1411: KeybdDriverVKeyToUnicode: No input language installed

google 半天的結果當然是無解.. (google 能找到答案的問題本來就不叫問題..), 如 debug console 所說, 這是欠輸入法, 但只講對 1/5, 實際上這除了欠輸入法以外, 還欠 keyboard layout. 而更奇怪的是, CE 上 keyboard layout 竟然是用輸入法所用的代號..

以下假設是日文環境, 輸入法用 IME 3.1, BSP會這樣設定:
[HKEY_CURRENT_USER\Keyboard Layout\Preload]
@="00000411"
[HKEY_CURRENT_USER\Keyboard Layout\Preload\1]
@="00000411"

這個在 \wince600\PUBLIC\COMMON\OAK\DRIVERS\KEYBD\LAYMGR.reg 裡, 而被 BSP 用的 platform.reg include 進來:

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\00000411]
"Layout File"="kbdmouse.dll"
"Layout Text"="Japanese"
"PS2_AT"="kbdmouse.dll"

但實際上這樣做有幾個問題在於
1.實際上沒有一個輸入法叫 00000411, 這是國家代碼, 當然不會是輸入法代碼..
2.IME 3.1 的輸入法代號叫 e001, 所以在 laymgr.cpp 中尋找的是 e0010411....
3.這個 e0010411 會在以上的 Preload 裡尋找, 如果沒有的話, 表示預設就沒有它..
4.這個 e0010411 也會 在 Layouts 裡尋找, 如果沒有, 就沒有對應表..

這個問題源自於 laymgr.cpp GetDefaultInputMethodName()中的一行
_tcsicmp( szTempInputMethodName, szTempDefaultInputMethodName)
(line 2963 at wince 6.0 R3 patch 2011-06-30) 中的判斷, 傳進去的是輸入法代碼 + 國碼一起比較, 也就所以為什麼英語語系 (00000409) 都沒有問題, 因為英語語系沒有輸入法, 前面都是0, 所以不會有找不到的問題.
(實際上我會建議在 laymgr.cpp 中安插自己的 debug message 把輸入法的代號 dump 出來, 以利日後 registery 值的建立.)

也就是說, 如果是用日文語系+IME的話, laymgr 會去找一個叫 "日文語系+IME" 的鍵盤, 實際上當然是不會有這種東西, 但我們要在 registery 裡造個假的去騙過檢查...

所以我現在用的設定是這樣子, 平臺是 FreeScale i.MX35

i.MX35 用的 platform registery key 在:
C:\WINCE600\PLATFORM\iMX35-3DS-PDK1_7\FILES\platform.reg
修改幾個:
; #include "$(DRIVERS_DIR)\keybd\LayMgr.reg" ;<= mark 掉
因為全域變數不一定 100% work, 所以被 include 進去的東西
往往會被設定成預設的 0409 而非想要的其它語系.

在最後面加上:
[HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\KEYBD]
"DriverName"="kbdmouse.dll" ;這是預設 driver.
[HKEY_CURRENT_USER\Keyboard Layout\Preload]
@="e0010411" ;預設使用的輸入法
[HKEY_CURRENT_USER\Keyboard Layout\Preload\1]
@="00000409" ;有這三個可以備選
[HKEY_CURRENT_USER\Keyboard Layout\Preload\2]
@="e0010411"
[HKEY_CURRENT_USER\Keyboard Layout\Preload\3]
@="00000411" ;這個是被列給 keyboard layout 用的.
[HKEY_LOCAL_MACHINE\Security\Policies]
@="00000411" ;這個不確定幹麻的.
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\00000409]
"Layout File"="kbdmouse.dll" ;其實這裡指的都是對應表.
"Layout Text"="US"
"PS2_AT"="kbdmouse.dll"
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\e0010411]
"Layout File"="KbdNopJpn1.dll" ;JPN IBM layout 是 jpn1, NEC 是 jpn2.
"Layout Text"="Japanese"
"PS2_AT"="KbdNopJpn1.dll"
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\00000411]
"Layout File"="KbdNopJpn1.dll" ;這裡也要再設定一個.
"Layout Text"="Japanese"

其中指定用 kbdnopjpn1.dll 的主要原因, 是因為它有 export PS2AT_00000411 跟 IL_00000411 兩個 function 出來, 這個是 CE 一拿到就會有已經建好的東西, 其它像法文鍵盤等, 就要參考網路上的文章 (也是被找到最多的文章..)

開機進 CE 裡後, 還要先把輸入法切回英數再切回 IME 才可以兩個都載入進來.

ps. OS component 中, international->locale_specific_support->Japanese->Keyboard 確定要選. 而 NOP-en., NOP keyboard/mouse japan2 這兩個其實一定要選, 才會有 kbdnopjpn1.dll 被包進 kernel image 中, 圖中是因為 BSP 還啥的影響不能全選:


不過仍有繞路走的解法. 在 sysgen 時, 會幾乎把所有不管你有用到沒用到的 .DLL 全部編譯, 先盡可能浪費你所有的時間後, 然後再看要不要加進來... 也就是說, 編好後, 用搜尋是可以搜尋的到這些 .DLL 檔案的. 把這些 .DLL 檔案抓出來後, 可以用內建檔案的玩法給它內建在 kernel image 裡.
也就是修改 platform.bib, 加上
KbdNopJpn1.dll $(_FLATRELEASEDIR)\KbdNopJpn1.dll NK U
這樣在執行時, 會擺在 \\windows\\ 下, 輸入法檔案是可以找的到的.

先這樣, 這還不是很好的解法...

沒有留言: