• 沒有找到結果。

附錄、㆗文輸入法簡介

N/A
N/A
Protected

Academic year: 2021

Share "附錄、㆗文輸入法簡介 "

Copied!
9
0
0

加載中.... (立即查看全文)

全文

(1)

附錄、㆗文輸入法簡介

微軟所發展出的WINDOW 作業系統,為了能夠輸入多語系的文字,尤其是 針對遠東㆞區很多國家的文字數眾多,無法像歐美只用8 個 BITS 就能表達出所 有的字母及數字,而需要用16 BITS 來表達文字。另外設計了 IME( Imput Method Editor),來處理遠東㆞區文字的輸入,目前國內關於微軟㆗文輸入法的介紹非常 的少,要撰寫㆗文輸入法的相關訊息,只有微軟所提供的技術網站㆖的技術文件 可參考[14],微軟另有提供完整的範例程式於

www.microsoft.com/ddk 之㆗。

(㆒)、Window ㆗文字輸入的訊息流程圖

Window ㆗文字輸入主要是透過 WINNLS.DLL (Window National

Language Support)動態連結函式庫結合輸入法(IME, Input Method Editor)來 完 成。在圖2-1 ㆗清楚說明彼此的關係。

㆗文字輸入的訊息流程圖11-1

(2)

以㆘說明㆗文字在輸入時處理的步驟:

1.當使用者敲㆘鍵盤時,這個鍵盤事件首先由 Windows ㆔大模組之㆒的 user.exe 接收。

2.user.exe 將這個鍵盤事件轉換成 WM_KeyDown 與_KeyWMUp 訊息,這兩 個訊息接著傳入 Winnls.DLL。

3.㆖述的訊息會再度經過 Winnls.DLL 轉換,以 wm_ImeKeyDown 與 wm_ImeKeyUp 傳給各輸入法(IME, Imput Method Editor)。

4.各個 IME 輸入法判斷傳入的鍵盤訊息, 並在 IME 視窗㆗顯示使用者鍵入 的按鍵(例如:倉頡的字根:日、月...等),當完成㆒個㆗文組合時, 將這個

㆗文字回報給 Winnls.DLL。

5.最後,Winnls.DLL 將㆗文字以 WM_Char 等訊息傳給目前作用㆗的應用程 式[15]。

(㆓)、IME 的結構

Window IME 由兩大元件所組成包含 IME Conversion Interface IME user Interface 。

1.IME Conversion Interface :

是由IME module 所支援的㆒組 function 所構成 (ex: ImmSetOpenStatus, ImmNotifyIME…),IMM 透過 IME module 所提供的 function 來控制 Conversion Interface。

2.IME User Interface:

是使用者所看到IME 的介面,也就是當我們選擇輸入法之後,在畫面㆖所 顯示的相關的IME 視窗(User Interface Window, status Window, composition Window ),作為使用者與 IME 之間的介面,若要撰寫㆗文輸入法,首先需要

(3)

IME User Interface ㆘手。

運用User Interface Window 之前需使用 Create WindowEx function 建立新 User Interface Window 。在執行時 User Interface Window 會收到 IME 的各 種不同的控制訊息,根據這些訊息User Interface Window 便會得知其需要完成 那些相對動作。

Create WindowEx function 的例子 :

hwnd = CreateWindowEx(WS_EX_WINDOWEDGE|

WS_EX_DLGMODALFRAME, szAppName, NULL,

WS_POPUP|WS_DISABLED|WS_BORDER, lpswImeL->xStatus,lpswImeL->yStatus, lpswImeL->xStatusWi, lpswImeL->yStatusHi, Huiwnd,NULL,hInstance, NULL);

程式 11-1 (1). IME class

IME class 是由 Window 作業系統所提供,Window 在 USER.EXE ㆗定義 IME class,IME class 掌控所有的來自於 IME 及應用程式㆗有使用 IMM 的 控制訊息, 應用程式需依靠IME class 來建立 User Interface Window。IME class 是無法被任何 IME 程式所取代,IME class 會根據 WM_IME_SELECT message ㆗所包含的 KHL 資訊找出相對的輸入法(注音,倉頡,英數…)建立 User Interface Window。

(2). DllMain

我們所發展的㆗文輸入法程式,其實是動態連結程式(DLL),提供給 IME 呼叫,在我們所寫的㆗文輸入法程式㆗定義了相關的IME 介面視窗,及如何 搜尋㆗文字庫,在microsoft VC++有提供 Compile 成 DLL 的功能(不㆒定要

(4)

microsoft 的 VC++,只要有提供編譯 DLL 功能的 Compiler 即可,例如 C++BUILDER 亦可),在 DLL ㆗有㆒個主程式叫 DllMain,當 DLL ㆒開始被 執行時,系統會發出DLL_PROCESS_ATTACH 呼叫 DllMain,之後將執行 AttachIME 在這個 PROCEDURE,其主要的動作為初始設定的工作,設定 IME 相關狀態的參數,其㆗包含 User Interface Window 的相關資料,另外 IME 結束時,系統會發出DLL_PROCESS_DETACH 呼叫 DllMain,程式㆗將執行 DetachIME 用來執行結束的收尾動作。

BOOL APIENTRY DllMain(

HINSTANCE hInstance, // instance handle of this library DWORD fdwReason, // reason called

LPVOID lpvReserve) // reserve pointer { switch (fdwReason) {

case DLL_PROCESS_ATTACH:

AttachIME(UIWndProc, CompWndProc, CandWndProc, StatusWndProc, OffCaretWndProc, ContextMenuWndProc);

break;

case DLL_PROCESS_DETACH:

DetachIME(lpInstL, lpImeL);

break; } return (TRUE);}

程式11-2 (3). UI class

UI class 的建立是發生在系統發出 DLL_PROCESS_ATTACH 呼叫 DllMain 之後,在 AttachIME 之㆗包含了建立 UI class 的程式片段,㆘面程式 範例㆗列出如何建立UI class 的部份程式,其㆗ wc.style 是指 class 的型態,

(5)

wc.style ㆒定必需包括 CS_IME type,輸入法才能運作正常,其㆗

szUIClassName 是 UI class 的名稱。

wc.style = CS_MYCLASSFLAG | CS_IME;

wc.lpfnWndProc = MyUIServerWndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 2 * sizeof(LONG);

wc.hInstance = hInst;

wc.hCursor = LoadCursor( NULL, IDC_ARROW );

wc.hIcon = NULL;

wc.lpszMenuName = (LPSTR)NULL;

wc.lpszClassName = (LPSTR)szUIClassName;

wc.hbrBackground = NULL;

if( !RegisterClass( (LPWNDCLASS)&wc ) ) return FALSE;

程式11-3 (4). User Interface Window:

以㆘列出部份User Interface Window 的處理程式,其在新建立 User Interface Window 時會呼叫 WM_CREATE,結束會呼叫 WM_DESTORY, 此時 可以利用此㆒特性加入自己的程式,在程式㆗黑體字的部份是原本微軟所提 供的程式所沒有的,我們可以在 WM_CREATE 之㆗加入呼叫自己的程式,但 別忘了加入DestroyUIWindow 於 WM_DESTROY 之㆗,讓 UI 程式結束工作 時同時也關閉自已所寫的程式,否則當切換輸入法時,將無法關閉自己所寫 的程式。

LRESULT CALLBACK UIWndProc( HWND hUIWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { static HWND Wnd,Wnd_k;

(6)

switch (uMsg) { case WM_CREATE:

CreateUIWindow(lpImeL, hUIWnd);

Wnd =CreateMy (hUIWnd,lpInstL->hInst);

Wnd_k=CreateKb (hUIWnd, lpInstL->hInst);

break;

case WM_DESTROY:

DestroyUIWindow(hUIWnd);

DestroyUIWindow(Wnd);

DestroyUIWindow(Wnd_k);

break;

case WM_IME_STARTCOMPOSITION:

// you can create a window as the composition window here StartComp( lpInstL, lpImeL, hUIWnd);

break;}

程式11-4 (5). InputContext

InputContext 是㆒種結構,其內容主要是 IME windows 的狀態,也就是 每㆒個THREAD 都有㆒相對的 Input Context,用來描述其 IME 的狀態。

InputContext 包含了㆕個元件:hCompStr, hCandInfo, hGuideLine, hPrivate or hMsgBuf,以㆘列出如何使用 InputContext 元件的方法,以取得組字字串為例 (hCompStr)。 採用 ImmLockIMC,ImmUnlockIMC 來取得 hCompStr。

LPINPUTCONTEXT lpIMC;

LPCOMOSITIONSTRING lpCompStr;

(7)

if (hIMC) // It is not NULL context.

{ lpIMC = ImmLockIMC(hIMC);

if (!lpIMC) {

MyError( “Can not lock hIMC”);

return FALSE;

}

lpCompStr =

(LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);

// Access lpCompStr.

ImmUnlockIMCC(lpIMC->hCompStr);

// ReSize lpIMC->hCompStr.

if (!(hMyCompStr = ImmReSizeIMCC(lpIMC->hCompStr,dwNewSize)) {

MyError(“Can not resize hCompStr”);

ImmUnlockIMC(hIMC);

return FALSE;

}

lpIMC->hCompStr = hMyCompStr;

ImmUnlockIMC(hIMC);}

程式11-5

每㆒個User Interface Window 都有其相對的 InputContext, 當 User Interface Window 收到 WM_IME_xxx message 時,需要針對 message 的內容 來執行相關的動作,此時往往需要取得InputContext 的內容,我們可利用 GetWindowLong( )配合 IMMGWL_HIMC 參數取得 InputContext,當 IME 需 要額外的空間來存放時 window instance ,亦可利用 GetWindowLong( )及 SetWindowLong( )配合 IMMGWL_HIMC 參數取得及設定 Long value 大小 的空間 用以存放Window Instance,若 User Interface Window 所需的空間超過 Long value, 可以直接記憶體區塊的 handle 放入 IMMGWL_HIMC 的位置

㆗。

(8)

以㆘列出相關的程式範例。

LRESULT UIWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

HIMC hIMC;

HGLOBAL hMyExtra;

switch(msg){

case WM_CREATE:

// Allocate the memory bloack for the window instance.

hMyExtra = GlobalAlloc(GHND,size_of_MyExtra);

if (!hMyExtra) MyError();

// Set the memory handle into IMMGWL_PRIVATE SetWindowLong(hWnd, IMMGWL_PRIVATE,

(LONG)hMyExtra);

break;

case WM_IME_xxxx:

// Get IMC;

hIMC = GetWindowLong(hWnd,IMMGWL_IMC);

// Get the memory handle for the window instance.

hMyExtra = GetWindowLong(hWnd, IMMGWL_PRIVATE);

lpMyExtra = GlobalLock(hMyExtra);

GlobalUnlock(hMyExtra);

break;

case WM_DESTROY:

// Get the memory handle for the window instance.

hMyExtra = GetWindowLong(hWnd, IMMGWL_PRIVATE);

// Free the memory block for the window instance.

GlobalFree(hMyExtra);

break;

default:

return DefWindowProc(hWnd, msg, wParam, lParam);

} }

程式11-6

(9)

(6). IME 介面函數

以㆘列出進行編譯輸入法時所需撰寫定義檔的內容(<IMENAME> .DEF) 在定義檔的內容㆗會出現”EXPORTS”的字樣,在EXPORTS之後就是需要由我 們撰寫提供給IME呼叫的IME 介面函數,說明如㆘:

i. ImeInquire:IME初始化的動作,傳回IME STRUCTURE,和UI class 的名 稱。

ii. ImeConversionList:輸入字串與結果字串的轉換。

iii. ImeConfigure:提供使用者,修改IME屬性的對話視窗。

iv. ImeDestroy:結束IME。

v. ImeEscape:透過 ImeEscape 可以讓應用程式,間接使用IMM APIs。

vi. ImeSetActiveContext:設定Input Context 為actived 或deactived vii. ImeProcessKey:判斷按鍵是否需要經IME處理。

viii. NotifyIME:IME傳送訊息給NotifyIME,處理訊息相對應的工作(ex.. 開 啟候選視窗,關閉候選窗視,更新設定Input Context…)

ix. ImeSelect:選擇 Input Context,進行 Input Context 初始化/非始化 (initialize/uninitialize)的動作。

x. ImeSetCompositionString:設定組字串結構,設定結束後IME將發出 WM_IME_COMPOSITION 的訊息。

xi. ImeToAsciiEx:根據 virkey code及scancode 轉換成相對應的結果,例如 假設目前輸入法處於輸入英數的狀態,此時若按㆘鍵盤㆖的”A”鍵,首 先經IME判斷是合法的動作,接㆘進行呼叫ImeToAsciiEx,送出”A”字元

xii. ImeRegisterWord,ImeUnregisterWord,ImeGetRegisterWordStyle,

及ImeEnumRegisterWord:處理自訂字庫的註冊及讀取的動作。

xiii. UIWndProc,CompWndProc,CandWndProc,StatusWndProc,

OffCaretWndProc,ContextMenuWndProc:User Interface Window的處理 程式。

參考文獻

相關文件

Google Science Journal 簡介..

 想要設計一個具有兩個輸入G(gate閘控)和 D(data資料)以及一個輸出Q的閘控閂電 路。當G等於1時,在輸入D出現的二進位資料

‡圖形使用者介面( graphical user interface GUI). ‡圖形使用者介面( graphical user

電視畫面信息豐富,不同人在解讀相同的視覺 畫面時,都有各自關注的地方,同時需要以自

– Each listener may respond to a different kind of  event or multiple listeners might may respond to event, or multiple listeners might may respond to 

(已立自己叩門的且在 2) , ,不經概愈化的東西。其中大部 分是「 」(聞自 DWE 閉門自 們閏月出自 EB

 社會故事是由父母或老師針對自閉症兒童的學習需

– If all the text fits in the view port then no scroll bars will be visible If all the text fits in the view port, then no scroll bars will be visible