Windows 95 输入法编辑器
Windows 95 輸入法編輯器 翻譯:戴石麟譯自微軟的MSDN DDK
?
關(guān)于Windows 95的多語言IME(輸入法編輯器)
在Windows 95中,IME以動態(tài)連接庫(DLL)的形式提供,與Windows 3.1東方版的IME不同,每個(gè)IME作為一個(gè)多語言鍵盤布局來運(yùn)行。與Windows 3.1 IME相比,Windows 95多語言IME具有下述優(yōu)勢:
- 作為多語言環(huán)境的一個(gè)組件來運(yùn)行?????
- 為每個(gè)應(yīng)用程序任務(wù)提供多個(gè)輸入場景?????
- 為每個(gè)應(yīng)用程序線程提供一個(gè)活動IME
- 通過應(yīng)用程序的消息循環(huán)(消息順序不變)為其提供信息?????
- 為對IME不敏感和對IME敏感的應(yīng)用程序均提供強(qiáng)大的支持
為了充分利用IME的優(yōu)勢,應(yīng)用程序需要支持Windows 95 IME應(yīng)用程序I/F。
本文描述Windows 95 IME體系的應(yīng)用程序I/F。
?
IME的結(jié)構(gòu)
Windows 95 IME必須提供兩個(gè)組件:IME轉(zhuǎn)換接口和IME用戶界面。IME轉(zhuǎn)換接口以一套從IME模塊輸出的函數(shù)提供。這些函數(shù)由IMM調(diào)用。IME用戶界面以一套窗口提供。這些窗口接收消息并提供IME的用戶界面。
?
IME敏感的應(yīng)用程序
有以下類型應(yīng)用程序:
- IME不敏感的應(yīng)用程序:這種類型的應(yīng)用程序絕不打算控制IME。但是,如果應(yīng)用程序接受DBCS字符,用戶可以用IME向應(yīng)用程序輸入任何DBCS字符。?????
- IME半敏感的應(yīng)用程序:這種類型的應(yīng)用程序通常控制IME的各種場景,如打開和關(guān)閉、工作窗口等,但是它不為IME顯示任何用戶界面。
- IME全敏感的應(yīng)用程序:這種類型的應(yīng)用程序通常顯示IME給它的任何信息。
在Windows 95中,一個(gè)對IME不敏感的應(yīng)用程序由一個(gè)默認(rèn)的IME窗口和一個(gè)默認(rèn)的輸入場景支持。
IME半敏感的應(yīng)用程序用預(yù)定義的"IME"類創(chuàng)建自己的IME窗口,可以處理也可以不處理自己的輸入場景。
IME全敏感的應(yīng)用程序自己處理輸入場景。它顯示輸入場景給出的任何必要的信息。它不使用IME窗口。
?
IME用戶界面
IME用戶界面包括IME窗口、用戶界面(UI)窗口和UI窗口的組件。
?
特點(diǎn)
IME類是預(yù)定義的全局窗口類,它實(shí)現(xiàn)IME的用戶界面部分。IME類有許多與預(yù)定義的公共控件窗口相同的特征。IME窗口實(shí)例可用CreateWindowEx函數(shù)來創(chuàng)建。象靜態(tài)控件一樣,IME類窗口自身不對用戶輸入作出反應(yīng);代之以接收各類控件消息來實(shí)現(xiàn)整個(gè)IME用戶界面。應(yīng)用程序可以用IME類創(chuàng)建自己的IME窗口,也可以用ImmGetDefaultIMEWnd函數(shù)來獲得默認(rèn)的IME窗口。創(chuàng)建自己的IME窗口或使用默認(rèn)的IME窗口的應(yīng)用程序稱為IME敏感的應(yīng)用程序,可以獲得下述益處(與Windows 3.1中類似應(yīng)用程序相比):
?
- 包含候選列表窗口,每個(gè)應(yīng)用程序可有自己的用戶界面窗口實(shí)例,所以用戶可以在任何操作的中途停下來,將輸入焦點(diǎn)改變到另一應(yīng)用程序。在Windows 3.1日文版中,在改變到另一應(yīng)用程序時(shí)用戶必須放棄操作。
- 因?yàn)镮ME用戶界面窗口擁有應(yīng)用程序的窗口句柄,因此它可以為應(yīng)用程序提供默認(rèn)的行為。例如,它可以隨應(yīng)用程序移動而自動移動,自動跟蹤窗口的光標(biāo)位置,指出每一應(yīng)用程序的狀態(tài)等。?????
?
雖然系統(tǒng)僅提供一個(gè)IME類,但仍有兩種IME窗口。一種類型由系統(tǒng)為IME不敏感的應(yīng)用程序創(chuàng)建。DefWindowsProc函數(shù)為這種窗口處理消息。DefWindowsProc函數(shù)的IME用戶界面為一個(gè)線程中所有IME不敏感的窗口所共享。在本文中,它叫做"默認(rèn)IME窗口"。其它窗口由IME敏感的應(yīng)用程序創(chuàng)建。在本文中,由IME敏感的應(yīng)用程序創(chuàng)建的窗口叫做"應(yīng)用程序IME窗口"。
?
默認(rèn)與應(yīng)用程序IME窗口
線程初始化時(shí),系統(tǒng)創(chuàng)建默認(rèn)IME窗口;也就是說,默認(rèn)IME窗口自動賦予線程。默認(rèn)IME窗口為IME不敏感的應(yīng)用程序提供IME用戶界面。當(dāng)IME或IMM生成一條IME消息(WM_IME_*)時(shí),對IME不敏感的應(yīng)用程序傳遞一條消息到DefWindowProc函數(shù)。DefWindowProc將所需的消息送到默認(rèn)IME窗口以為應(yīng)用程序提供默認(rèn)IME用戶界面。IME敏感的應(yīng)用程序在不從IME掛接消息時(shí)也使用默認(rèn)IME窗口。應(yīng)用程序僅在需要的時(shí)候使用自己的應(yīng)用程序IME窗口。
?
IME類
IME類是Windows 95-FE格式的預(yù)定義窗口類,就象Edit是預(yù)定義類一樣。預(yù)定義IME類處理IME的整個(gè)用戶界面,處理來自IME和應(yīng)用程序(包含IMM函數(shù))的所有控制消息。應(yīng)用程序用IME類創(chuàng)建自己的IME用戶界面。系統(tǒng)IME類不會被任何IME替換。
與IME類相聯(lián)系的窗口類處理WM_IME_SELECT消息。這條消息包括新選擇的IME的鍵盤布局。IME類使用鍵盤布局來獲取由每個(gè)IME定義的類名。IME類使用類名為當(dāng)前活動IME創(chuàng)建用戶界面窗口。
?
來自IME的UI類
每個(gè)IME都必須向系統(tǒng)注冊自己的用戶界面(UI)類。UI類提供特定的IME功能。IME在附著進(jìn)程時(shí)注冊自己的類;也就是說,用DLL_PROCESS_ATTACH調(diào)用DllEntry函數(shù)時(shí)。IME在調(diào)用ImeInquire函數(shù)時(shí)必須指明UI類名。UI類應(yīng)當(dāng)以CS_IME風(fēng)格注冊,以便每個(gè)應(yīng)用程序都能使用該UI類。UI類名(包括空結(jié)束符)可達(dá)16個(gè)TCHAR字符。此限制可能會在Windows的未來版本中得到擴(kuò)展。
?
當(dāng)注冊用戶界面類時(shí),你應(yīng)當(dāng)指明八個(gè)字節(jié)的額外窗口數(shù)據(jù)(即,將WNDCLASSEX結(jié)構(gòu)的cbWndExtra成員設(shè)置為2*sizeof(LONG)。這額外的窗口數(shù)據(jù)由系統(tǒng)使用。
?
IME在為應(yīng)用程序完成任務(wù)時(shí)可注冊任何類和創(chuàng)建任何窗口。
?
以下例子顯示如何注冊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窗口由應(yīng)用程序或由系統(tǒng)創(chuàng)建。當(dāng)IME窗口創(chuàng)建時(shí),由IME本身提供的UI窗口被IME窗口創(chuàng)建并擁有。每個(gè)UI窗口都有一個(gè)當(dāng)前輸入場景。你可以在UI窗口收到一條IME消息(WM_IME_*)時(shí),通過調(diào)用GetWindowLong函數(shù)并指明IMMGWL_IMC索引值來獲取輸入場景。UI窗口可以參照此輸入場景并處理消息。UI窗口可以在除對WM_CREATE消息作出反應(yīng)時(shí)以外的任何時(shí)候獲取輸入場景。
IME決不能更改UI窗口的額外窗口數(shù)據(jù)。如果你的窗口實(shí)例需要額外窗口數(shù)據(jù),你可以用SetWindowLong和GetWindowLong函數(shù)帶IMMGWL_PRIVATE參數(shù)。IMMGWL_PRIVATE參數(shù)提供對UI窗口實(shí)例額外數(shù)據(jù)的一個(gè)LONG值的訪問,你可將一內(nèi)存塊的句柄存入IMMGWL_PRIVATE區(qū)域。
?
UI窗口過程可以使用DefWindowProc函數(shù),但是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窗口在當(dāng)前選定的輸入場景中完成動作。當(dāng)窗口激活時(shí),UI窗口收到一條提供當(dāng)前輸入場景的消息。在此之后,UI窗口在當(dāng)前選定的輸入場景中運(yùn)行。輸入場景必須提供UI窗口顯示工作窗口、狀態(tài)窗口等所需的所有信息。
UI窗口參照輸入場景,但它不必自己刷新該場景。當(dāng)UI窗口需要刷新輸入場景時(shí),它應(yīng)當(dāng)調(diào)用IMM函數(shù),因?yàn)檩斎雸鼍笆怯蒊MM管理的。當(dāng)輸入場景改變時(shí),IMM和IME都收到通知。
?
例如,有時(shí)當(dāng)鼠標(biāo)點(diǎn)擊時(shí),UI窗口需要改變輸入場景的轉(zhuǎn)換模式。要設(shè)置轉(zhuǎn)換模式,UI窗口調(diào)用ImmSetConversionMode函數(shù)來為NotifyIME生成一條通知并將WM_IME_NOTIFY消息送至UI窗口。如果UI窗口要改變轉(zhuǎn)換模式的顯示,UI窗口應(yīng)當(dāng)?shù)却齏M_IME_NOTIFY消息。
?
UI窗口的組件
UI窗口可以參照當(dāng)前輸入場景來注冊和顯示工作窗口和狀態(tài)窗口。UI窗口組件的類風(fēng)格必須包含CS_IME。UI窗口實(shí)例從當(dāng)前輸入場景接收諸如工作字串、字型、位置之類的信息。上應(yīng)用程序的一個(gè)窗口獲得焦點(diǎn)時(shí),系統(tǒng)收到為窗口所擁有的輸入場景并將當(dāng)前輸入場景設(shè)置給UI窗口。系統(tǒng)將帶有輸入場景句柄的WM_IME_SETCONTEXT消息送到應(yīng)用程序,應(yīng)用程序?qū)⒋讼鬟f到UI窗口。如果當(dāng)前輸入場景被替換,UI窗口應(yīng)當(dāng)重畫工作窗口。每當(dāng)當(dāng)前場景變化,UI窗口都會顯示正確的工作窗口,確保IME的狀態(tài)。
UI窗口可以創(chuàng)建自己的字窗口或彈出窗口來顯示其狀態(tài)、工作字串或候選名單。這些窗口必須為UI窗口所擁有,并創(chuàng)建為失效窗口。IME創(chuàng)建的任何窗口都不應(yīng)當(dāng)獲得焦點(diǎn)。
?
輸入場景
?
默認(rèn)輸入場景
系統(tǒng)通過默認(rèn)給每個(gè)線程一個(gè)輸入場景。該場景為該線程所有對IME不敏感的窗口共享。
?
將輸入場景與窗口相關(guān)聯(lián)
應(yīng)用程序的窗口將其窗口句柄與輸入場景相關(guān)聯(lián)來維持IME狀態(tài),包括當(dāng)前工作字串。一旦應(yīng)用程序?qū)⑤斎雸鼍芭c窗口句柄相關(guān)聯(lián),系統(tǒng)在窗口激活時(shí)將自動選擇該場景。利用此特征,應(yīng)用程序?qū)⒉恍柘笤赪indows 3.1下那樣進(jìn)行復(fù)雜的獲得、放棄焦點(diǎn)的處理。
?
使用輸入場景
當(dāng)應(yīng)用程序或系統(tǒng)創(chuàng)建新的輸入場景時(shí),系統(tǒng)準(zhǔn)備新的輸入場景。新的輸入場景已經(jīng)包括IMCC,即由hCompStr、hCandInfo、hGuideLine、hPrivate和hMsgBuf組成的IMC的組件。IME基本上不需創(chuàng)建輸入場景和輸入場景的組件。IME可以通過鎖定它們來改變其大小并能獲得指向組件的指針。
?
訪問HIMC
要訪問輸入場景,IME必須調(diào)用ImmLockIMC來獲得指向輸入場景的指針。ImmLockIMC遞增IMC的IMM鎖定記數(shù),而ImmUnlockIMC則遞減它。
?
訪問HIMCC
要訪問輸入場景的一個(gè)組件,IME必須調(diào)用ImmLockIMCC來獲得指向IMCC的指針。ImmLockIMCC遞增IMCC的IMM鎖定記數(shù),而ImmUnlockIMC則遞減它。ImmReSizeIMCC可以將IMCC調(diào)整至特定的大小。
?
有時(shí),IME可能需要自己創(chuàng)建輸入場景的一個(gè)組件。在這種情況下,IME可以調(diào)用ImmCreateIMCC函數(shù)并獲得IMCC的句柄。該IMCC可以是INPUTCONTEXT結(jié)構(gòu)的成員(hCompStr、hCandInfo、hGuideLine、hPrivate或hMsgBuf)。
ImmDestroyIMCC銷毀輸入場景的一個(gè)組件。
?
怎樣使用輸入場景
以下例子顯示如何使用輸入場景:
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消息。當(dāng)IME開始一次回話時(shí),IME必須生成WM_IME_STARTCOMPOSITION消息。如果IME改變工作字符串,IME必須生成WM_IME_COMPOSITION消息。從IME來的事件是通過向與輸入場景相關(guān)聯(lián)的窗口生成消息來實(shí)現(xiàn)的。IME基本上是利用ImeToAsciiEx函數(shù)的參數(shù)所提供的lpdwTransKey緩沖區(qū)來生成消息的。當(dāng)ImeToAsciiEx被調(diào)用時(shí),IME將消息放進(jìn)lpdwTransKey緩沖區(qū)。即使ImeToAsciiEx未被調(diào)用,IME還是能夠利用輸入場景的消息緩沖區(qū)向與輸入場景相關(guān)聯(lián)的窗口生成消息。輸入場景以內(nèi)存塊句柄的形式擁有消息緩沖區(qū)。IME將消息放進(jìn)由消息緩沖區(qū)句柄提供的內(nèi)存塊中。然后,IME調(diào)用ImmGenerateMessage。ImmGenerateMessage函數(shù)將存儲于消息緩沖區(qū)里的消息發(fā)送到適當(dāng)?shù)拇翱凇?/p>
?
(注:我沒有翻譯完,在北大中文論壇上有更全的,請參見http://www.pkucn.com/thread-189364-1-1.html)
轉(zhuǎn)載于:https://www.cnblogs.com/sbxlm/p/3474020.html
總結(jié)
以上是生活随笔為你收集整理的Windows 95 输入法编辑器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代码编辑器
- 下一篇: 机器人手眼标定原理介绍(含详细推导过程)