Windows 95 输入法编辑器
Windows 95 輸入法編輯器 翻譯:戴石麟譯自微軟的MSDN DDK
?
關于Windows 95的多語言IME(輸入法編輯器)
在Windows 95中,IME以動態連接庫(DLL)的形式提供,與Windows 3.1東方版的IME不同,每個IME作為一個多語言鍵盤布局來運行。與Windows 3.1 IME相比,Windows 95多語言IME具有下述優勢:
- 作為多語言環境的一個組件來運行?????
- 為每個應用程序任務提供多個輸入場景?????
- 為每個應用程序線程提供一個活動IME
- 通過應用程序的消息循環(消息順序不變)為其提供信息?????
- 為對IME不敏感和對IME敏感的應用程序均提供強大的支持
為了充分利用IME的優勢,應用程序需要支持Windows 95 IME應用程序I/F。
本文描述Windows 95 IME體系的應用程序I/F。
?
IME的結構
Windows 95 IME必須提供兩個組件:IME轉換接口和IME用戶界面。IME轉換接口以一套從IME模塊輸出的函數提供。這些函數由IMM調用。IME用戶界面以一套窗口提供。這些窗口接收消息并提供IME的用戶界面。
?
IME敏感的應用程序
有以下類型應用程序:
- IME不敏感的應用程序:這種類型的應用程序絕不打算控制IME。但是,如果應用程序接受DBCS字符,用戶可以用IME向應用程序輸入任何DBCS字符。?????
- IME半敏感的應用程序:這種類型的應用程序通常控制IME的各種場景,如打開和關閉、工作窗口等,但是它不為IME顯示任何用戶界面。
- IME全敏感的應用程序:這種類型的應用程序通常顯示IME給它的任何信息。
在Windows 95中,一個對IME不敏感的應用程序由一個默認的IME窗口和一個默認的輸入場景支持。
IME半敏感的應用程序用預定義的"IME"類創建自己的IME窗口,可以處理也可以不處理自己的輸入場景。
IME全敏感的應用程序自己處理輸入場景。它顯示輸入場景給出的任何必要的信息。它不使用IME窗口。
?
IME用戶界面
IME用戶界面包括IME窗口、用戶界面(UI)窗口和UI窗口的組件。
?
特點
IME類是預定義的全局窗口類,它實現IME的用戶界面部分。IME類有許多與預定義的公共控件窗口相同的特征。IME窗口實例可用CreateWindowEx函數來創建。象靜態控件一樣,IME類窗口自身不對用戶輸入作出反應;代之以接收各類控件消息來實現整個IME用戶界面。應用程序可以用IME類創建自己的IME窗口,也可以用ImmGetDefaultIMEWnd函數來獲得默認的IME窗口。創建自己的IME窗口或使用默認的IME窗口的應用程序稱為IME敏感的應用程序,可以獲得下述益處(與Windows 3.1中類似應用程序相比):
?
- 包含候選列表窗口,每個應用程序可有自己的用戶界面窗口實例,所以用戶可以在任何操作的中途停下來,將輸入焦點改變到另一應用程序。在Windows 3.1日文版中,在改變到另一應用程序時用戶必須放棄操作。
- 因為IME用戶界面窗口擁有應用程序的窗口句柄,因此它可以為應用程序提供默認的行為。例如,它可以隨應用程序移動而自動移動,自動跟蹤窗口的光標位置,指出每一應用程序的狀態等。?????
?
雖然系統僅提供一個IME類,但仍有兩種IME窗口。一種類型由系統為IME不敏感的應用程序創建。DefWindowsProc函數為這種窗口處理消息。DefWindowsProc函數的IME用戶界面為一個線程中所有IME不敏感的窗口所共享。在本文中,它叫做"默認IME窗口"。其它窗口由IME敏感的應用程序創建。在本文中,由IME敏感的應用程序創建的窗口叫做"應用程序IME窗口"。
?
默認與應用程序IME窗口
線程初始化時,系統創建默認IME窗口;也就是說,默認IME窗口自動賦予線程。默認IME窗口為IME不敏感的應用程序提供IME用戶界面。當IME或IMM生成一條IME消息(WM_IME_*)時,對IME不敏感的應用程序傳遞一條消息到DefWindowProc函數。DefWindowProc將所需的消息送到默認IME窗口以為應用程序提供默認IME用戶界面。IME敏感的應用程序在不從IME掛接消息時也使用默認IME窗口。應用程序僅在需要的時候使用自己的應用程序IME窗口。
?
IME類
IME類是Windows 95-FE格式的預定義窗口類,就象Edit是預定義類一樣。預定義IME類處理IME的整個用戶界面,處理來自IME和應用程序(包含IMM函數)的所有控制消息。應用程序用IME類創建自己的IME用戶界面。系統IME類不會被任何IME替換。
與IME類相聯系的窗口類處理WM_IME_SELECT消息。這條消息包括新選擇的IME的鍵盤布局。IME類使用鍵盤布局來獲取由每個IME定義的類名。IME類使用類名為當前活動IME創建用戶界面窗口。
?
來自IME的UI類
每個IME都必須向系統注冊自己的用戶界面(UI)類。UI類提供特定的IME功能。IME在附著進程時注冊自己的類;也就是說,用DLL_PROCESS_ATTACH調用DllEntry函數時。IME在調用ImeInquire函數時必須指明UI類名。UI類應當以CS_IME風格注冊,以便每個應用程序都能使用該UI類。UI類名(包括空結束符)可達16個TCHAR字符。此限制可能會在Windows的未來版本中得到擴展。
?
當注冊用戶界面類時,你應當指明八個字節的額外窗口數據(即,將WNDCLASSEX結構的cbWndExtra成員設置為2*sizeof(LONG)。這額外的窗口數據由系統使用。
?
IME在為應用程序完成任務時可注冊任何類和創建任何窗口。
?
以下例子顯示如何注冊IME窗口類:
BOOL WINAPI DLLEntry (
??? HINSTANCE??? hInstDLL,
??? DWORD??????? dwFunction,
??? LPVOID?????? lpNot)
{
??? switch (dwFunction) {
??????? case DLL_PROCESS_ATTACH:
? ??????????hInst= hInstDLL;
?
??????????? 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;
?
??????????? wc.style????????? = CS_MYCLASSFLAG | CS_IME;
??????????? wc.lpfnWndProc??? = MyCompStringWndProc;
??????????? wc.cbClsExtra???? = 0;
??????????? wc.cbWndExtra???? = cbMyWndExtra;
??????????? wc.hInstance????? = hInst;
??????????? wc.hCursor??????? = LoadCursor(NULL, IDC_ARROW);
??????????? wc.hIcon????????? = NULL;
??????????? wc.lpszMenuName?? = (LPSTR) NULL;
??????????? wc.lpszClassName? = (LPSTR) szUICompStringClassName;
???? ???????wc.hbrBackground? = NULL;
?
??????????? if(!RegisterClass((LPWNDCLASS)&wc))
??????????????? return FALSE;
?
??????????? break;
?
??????? case DLL_PROCESS_DETACH:
??????????? UnregisterClass(szUIClassName,hInst);
??????????? UnregisterClass(szUICompStringClassName,hInst);
??????????? break;
??? }
??? return TRUE;
}
?
UI窗口
IME類的IME窗口由應用程序或由系統創建。當IME窗口創建時,由IME本身提供的UI窗口被IME窗口創建并擁有。每個UI窗口都有一個當前輸入場景。你可以在UI窗口收到一條IME消息(WM_IME_*)時,通過調用GetWindowLong函數并指明IMMGWL_IMC索引值來獲取輸入場景。UI窗口可以參照此輸入場景并處理消息。UI窗口可以在除對WM_CREATE消息作出反應時以外的任何時候獲取輸入場景。
IME決不能更改UI窗口的額外窗口數據。如果你的窗口實例需要額外窗口數據,你可以用SetWindowLong和GetWindowLong函數帶IMMGWL_PRIVATE參數。IMMGWL_PRIVATE參數提供對UI窗口實例額外數據的一個LONG值的訪問,你可將一內存塊的句柄存入IMMGWL_PRIVATE區域。
?
UI窗口過程可以使用DefWindowProc函數,但是UI窗口不能將IME消息傳遞給DefWindowProc。即使一條IME消息未被UI窗口過程處理,UI窗口也不能將它傳遞給DefWindowProc。
?
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);
?
??? }
}
?
UI窗口在當前選定的輸入場景中完成動作。當窗口激活時,UI窗口收到一條提供當前輸入場景的消息。在此之后,UI窗口在當前選定的輸入場景中運行。輸入場景必須提供UI窗口顯示工作窗口、狀態窗口等所需的所有信息。
UI窗口參照輸入場景,但它不必自己刷新該場景。當UI窗口需要刷新輸入場景時,它應當調用IMM函數,因為輸入場景是由IMM管理的。當輸入場景改變時,IMM和IME都收到通知。
?
例如,有時當鼠標點擊時,UI窗口需要改變輸入場景的轉換模式。要設置轉換模式,UI窗口調用ImmSetConversionMode函數來為NotifyIME生成一條通知并將WM_IME_NOTIFY消息送至UI窗口。如果UI窗口要改變轉換模式的顯示,UI窗口應當等待WM_IME_NOTIFY消息。
?
UI窗口的組件
UI窗口可以參照當前輸入場景來注冊和顯示工作窗口和狀態窗口。UI窗口組件的類風格必須包含CS_IME。UI窗口實例從當前輸入場景接收諸如工作字串、字型、位置之類的信息。上應用程序的一個窗口獲得焦點時,系統收到為窗口所擁有的輸入場景并將當前輸入場景設置給UI窗口。系統將帶有輸入場景句柄的WM_IME_SETCONTEXT消息送到應用程序,應用程序將此消息傳遞到UI窗口。如果當前輸入場景被替換,UI窗口應當重畫工作窗口。每當當前場景變化,UI窗口都會顯示正確的工作窗口,確保IME的狀態。
UI窗口可以創建自己的字窗口或彈出窗口來顯示其狀態、工作字串或候選名單。這些窗口必須為UI窗口所擁有,并創建為失效窗口。IME創建的任何窗口都不應當獲得焦點。
?
輸入場景
?
默認輸入場景
系統通過默認給每個線程一個輸入場景。該場景為該線程所有對IME不敏感的窗口共享。
?
將輸入場景與窗口相關聯
應用程序的窗口將其窗口句柄與輸入場景相關聯來維持IME狀態,包括當前工作字串。一旦應用程序將輸入場景與窗口句柄相關聯,系統在窗口激活時將自動選擇該場景。利用此特征,應用程序將不需象在Windows 3.1下那樣進行復雜的獲得、放棄焦點的處理。
?
使用輸入場景
當應用程序或系統創建新的輸入場景時,系統準備新的輸入場景。新的輸入場景已經包括IMCC,即由hCompStr、hCandInfo、hGuideLine、hPrivate和hMsgBuf組成的IMC的組件。IME基本上不需創建輸入場景和輸入場景的組件。IME可以通過鎖定它們來改變其大小并能獲得指向組件的指針。
?
訪問HIMC
要訪問輸入場景,IME必須調用ImmLockIMC來獲得指向輸入場景的指針。ImmLockIMC遞增IMC的IMM鎖定記數,而ImmUnlockIMC則遞減它。
?
訪問HIMCC
要訪問輸入場景的一個組件,IME必須調用ImmLockIMCC來獲得指向IMCC的指針。ImmLockIMCC遞增IMCC的IMM鎖定記數,而ImmUnlockIMC則遞減它。ImmReSizeIMCC可以將IMCC調整至特定的大小。
?
有時,IME可能需要自己創建輸入場景的一個組件。在這種情況下,IME可以調用ImmCreateIMCC函數并獲得IMCC的句柄。該IMCC可以是INPUTCONTEXT結構的成員(hCompStr、hCandInfo、hGuideLine、hPrivate或hMsgBuf)。
ImmDestroyIMCC銷毀輸入場景的一個組件。
?
怎樣使用輸入場景
以下例子顯示如何使用輸入場景:
LPINPUTCONTEXT lpIMC;
LPCOMOSITIONSTRING lpCompStr;
HIMCC hMyCompStr;
?
if (hIMC) { // It is not NULL context.
??? lpIMC = ImmLockIMC(hIMC);
?
??? if (!lpIMC) {
??????? MyError( "Can not lock hIMC");
??????? return FALSE;
??? }
?
??? // Use lpIMC->hCompStr.
??? 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);
}
?
生成消息
IME需要生成IME消息。當IME開始一次回話時,IME必須生成WM_IME_STARTCOMPOSITION消息。如果IME改變工作字符串,IME必須生成WM_IME_COMPOSITION消息。從IME來的事件是通過向與輸入場景相關聯的窗口生成消息來實現的。IME基本上是利用ImeToAsciiEx函數的參數所提供的lpdwTransKey緩沖區來生成消息的。當ImeToAsciiEx被調用時,IME將消息放進lpdwTransKey緩沖區。即使ImeToAsciiEx未被調用,IME還是能夠利用輸入場景的消息緩沖區向與輸入場景相關聯的窗口生成消息。輸入場景以內存塊句柄的形式擁有消息緩沖區。IME將消息放進由消息緩沖區句柄提供的內存塊中。然后,IME調用ImmGenerateMessage。ImmGenerateMessage函數將存儲于消息緩沖區里的消息發送到適當的窗口。
?
(注:我沒有翻譯完,在北大中文論壇上有更全的,請參見http://www.pkucn.com/thread-189364-1-1.html)
轉載于:https://www.cnblogs.com/sbxlm/p/3474020.html
總結
以上是生活随笔為你收集整理的Windows 95 输入法编辑器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代码编辑器
- 下一篇: java信息管理系统总结_java实现科