?? 輸入法編程指南.htm
字號(hào):
<TBODY>
<TR>
<TD></TD></TR></TBODY></TABLE>輸入法編程指南(根據(jù)msdn翻譯)
<P>作者: <FONT color=#0000ff>李麗
</FONT>,如轉(zhuǎn)載請(qǐng)保證本文檔的完整性,并注明出處。<BR><FONT color=#ffffff>歡迎光臨 C++
Builder
研究,http://www.ccrun.com/doc/go.asp?id=590</FONT><BR>Windows
95輸入法編輯器(IME) <BR>原著:Microsoft <BR>翻譯:TBsoft Software Studio
<BR>一、關(guān)于Windows 95混合語(yǔ)言IME <BR> 在Windows
95中,IME是一個(gè)動(dòng)態(tài)鏈接庫(kù)(DLL),與Windows
3.1遠(yuǎn)東版本IME不同的是,每一個(gè)運(yùn)行的IME相當(dāng)于混合語(yǔ)言鍵盤布局中的一種。與Windows 3.1
IME相比較,Windows 95混合語(yǔ)言IME提供下列增強(qiáng)功能:
<BR> ●運(yùn)行時(shí)相當(dāng)于混合語(yǔ)言環(huán)境的一個(gè)部件
<BR> ●為每一個(gè)應(yīng)用程序任務(wù)提供多重輸入上下文
<BR> ●為每一個(gè)應(yīng)用程序線程提供一個(gè)活動(dòng)的IME
<BR> ●通過(guò)應(yīng)用程序消息循環(huán)給應(yīng)用程序提供信息(消息順序不能改變)
<BR> ●為無(wú)IME支持應(yīng)用程序和部分IME支持應(yīng)用程序提供有力的支持
<BR> 要得到全部的增強(qiáng)功能,應(yīng)用程序需要支持Windows 95
IME應(yīng)用程序I/F。 <BR> 本文檔描述了Windows 95
IME體系結(jié)構(gòu)的應(yīng)用程序I/F。 <BR><BR>1、IME的結(jié)構(gòu)
<BR> Windows 95
IME必須提供兩個(gè)部件:IME轉(zhuǎn)換接口和IME用戶接口。IME轉(zhuǎn)換接口由一組IME模塊引出函數(shù)提供,這些函數(shù)被IMM(輸入法管理器——譯者注)調(diào)用。
<BR> IME用戶接口由一組窗口提供,這些窗口接收消息并提供IME的用戶界面。<BR><BR>2、IME支持應(yīng)用程序(IME感知應(yīng)用程序——譯者注)
<BR> 應(yīng)用程序有下列類型:
<BR>●無(wú)IME支持應(yīng)用程序:這種應(yīng)用程序不控制IME,然而,如果應(yīng)用程序接受DBCS字符,用戶可以通過(guò)IME在應(yīng)用程序中輸入DBCS字符。
<BR>●部分IME支持應(yīng)用程序:這種應(yīng)用程序只控制不同的IME上下文,例如打開(kāi)和關(guān)閉IME、寫(xiě)作窗口等等,但是不重新顯示任何IME用戶界面。
<BR>●完全I(xiàn)ME支持應(yīng)用程序:這種應(yīng)用程序負(fù)責(zé)管理通過(guò)IME顯示給應(yīng)用程序的任何信息。
<BR> 在Windows
95中,一個(gè)無(wú)IME支持應(yīng)用程序有一個(gè)缺省的IME窗口和一個(gè)缺省的輸入上下文。
<BR> 部分IME支持應(yīng)用程序使用預(yù)定義的“IME”類創(chuàng)建自己的IME窗口,可以管理或者不管理自己的輸入上下文。
<BR> 完全I(xiàn)ME支持應(yīng)用程序自己管理輸入上下文,顯示輸入上下文給出的任何需要的信息,不使用IME窗口。<BR>二、IME用戶界面
<BR> IME用戶界面包括IME窗口、用戶界面(UI)窗口以及UI窗口的部件。<BR><BR>1、特征
<BR> IME類是實(shí)現(xiàn)IME用戶界面部分的預(yù)定義全局窗口類。“IME”類與預(yù)定義的公共控制窗口類有許多相同的特點(diǎn),IME窗口實(shí)例與靜態(tài)控制一樣通過(guò)CreateWindowEx函數(shù)創(chuàng)建,IME類窗口自己不響應(yīng)用戶輸入,取而代之的是接收不同類型的控制消息實(shí)現(xiàn)全部IME用戶接口。應(yīng)用程序可以使用IME類創(chuàng)建自己的IME窗口,還可以使用ImmGetDefaultIMEWnd函數(shù)獲取缺省IME窗口。創(chuàng)建自己的IME窗口或者使用缺省IME窗口的應(yīng)用程序被稱為IME支持應(yīng)用程序,具有以下優(yōu)點(diǎn)(與對(duì)應(yīng)的Windows3.1應(yīng)用程序比較):<BR><BR>●包括候選字列表窗口(候選窗口),每一個(gè)應(yīng)用程序可以有自己的用戶界面窗口實(shí)例,使得用戶可以在任何輸入過(guò)程的中途停止并切換到另一個(gè)應(yīng)用程序。在Windows
3.1日文版本中,用戶切換到另一個(gè)應(yīng)用程序是必須放棄當(dāng)前輸入過(guò)程。
<BR>●因?yàn)镮ME用戶界面窗口包括應(yīng)用程序窗口句柄,IME用戶界面窗口可以為應(yīng)用程序提供缺省行為。例如當(dāng)應(yīng)用程序移動(dòng)時(shí)IME用戶界面窗口自動(dòng)移動(dòng),自動(dòng)跟隨窗口中的插入符號(hào)位置,為每一個(gè)應(yīng)用程序標(biāo)示模式等等。
<BR> 即使系統(tǒng)僅僅只提供一個(gè)IME類,IME窗口仍然有兩種類型。一種類型是系統(tǒng)為無(wú)IME支持應(yīng)用程序創(chuàng)建的IME窗口,DefWindowProc函數(shù)為該窗口處理消息,DefWindowProc函數(shù)的IME用戶接口被線程的所有無(wú)IME支持窗口共享,在文檔中,這種窗口稱為缺省IME窗口。另一種類型是IME支持應(yīng)用程序創(chuàng)建的IME窗口,在文檔中,IME支持應(yīng)用程序創(chuàng)建的IME窗口稱作應(yīng)用程序IME窗口。
<BR><BR>2、缺省和應(yīng)用程序IME窗口
<BR> 當(dāng)線程初始化時(shí)系統(tǒng)創(chuàng)建缺省IME窗口,這就是說(shuō),線程自動(dòng)獲取缺省IME窗口。缺省IME窗口為無(wú)IME支持應(yīng)用程序提供IME用戶界面,當(dāng)IME或者IMM生成一個(gè)IME消息(WM_IME_*)時(shí),無(wú)IME支持應(yīng)用程序傳遞該消息到DefWindowProc函數(shù),DefWindowProc函數(shù)發(fā)送需要的消息到為應(yīng)用程序提供缺省IME用戶界面的缺省IME窗口。IME支持應(yīng)用程序當(dāng)不從IME獲取消息時(shí)也可以使用缺省IME窗口,需要時(shí)可以使用自身的IME窗口。<BR><BR>3、IME類
<BR> IME類是Windows
95遠(yuǎn)東版本預(yù)定義的窗口類,就像Edit是預(yù)定義的窗口類一樣。預(yù)定義的IME類實(shí)現(xiàn)全部的IME用戶接口,處理所有來(lái)自IME和包含IMM函數(shù)的應(yīng)用程序的消息,應(yīng)用程序使用IME類創(chuàng)建自己的IME窗口。系統(tǒng)IME類不能被被任何IME替換。
<BR> 窗口過(guò)程與IME類通過(guò)WM_IME_SELECT消息交互,該消息包括新選中的IME的鍵盤布局,IME類使用鍵盤布局查找到每一個(gè)IME定義的類名。使用類名,IME類為當(dāng)前活動(dòng)的IME創(chuàng)建IME用戶界面窗口。
<BR><BR>4、IME UI類
<BR> 每一個(gè)IME必須向系統(tǒng)注冊(cè)自己的用戶界面(UI)類,UI類提供IME相關(guān)功能。當(dāng)IME附加在進(jìn)程上時(shí)IME注冊(cè)自己的UI類,這就是說(shuō),當(dāng)DLLEntry函數(shù)被調(diào)用DLL_PROCESS_ATTACH功能時(shí),IME必須在對(duì)ImeInquire函數(shù)的調(diào)用過(guò)程中指定UI類名。UI類應(yīng)該使用CS_IME窗口風(fēng)格注冊(cè)以使得每一個(gè)應(yīng)用程序都可以使用UI類。
<BR> UI類名(包括空終結(jié)符)可以使用16位的TCHAR字符,這個(gè)限制可能延續(xù)到Windows的未來(lái)版本。
<BR> 當(dāng)注冊(cè)一個(gè)UI類時(shí),應(yīng)該指定8個(gè)字節(jié)的窗口附加數(shù)據(jù)(這就是說(shuō),設(shè)置WNDCLASSEX類的cbWndExtra成員的值為2*sizeof(LONG)),系統(tǒng)使用該窗口附加數(shù)據(jù)。
<BR> IME可以在為應(yīng)用程序執(zhí)行任務(wù)時(shí)注冊(cè)任何類和創(chuàng)建任何窗口。
<BR><BR> 下面的實(shí)例顯示了怎樣注冊(cè)IME窗口類:
<BR><BR>BOOL WINAPI DLLEntry ( HINSTANCE hInstDLL, DWORD
dwFunction, LPVOID lpNot) <BR>{
<BR> switch (dwFunction)
<BR> {
<BR> case
DLL_PROCESS_ATTACH:
<BR> hInst=
hInstDLL;
<BR> wc.style =
CS_MYCLASSFLAG | CS_IME;
<BR> wc.lpfnWndProc
= MyUIServerWndProc;
<BR> wc.cbClsExtra
= 0;
<BR> wc.cbWndExtra
= 2 * sizeof(LONG);
<BR> wc.hInstance
= hInst;
<BR> wc.hCursor
= LoadCursor( NULL, IDC_ARROW);
<BR> wc.hIcon =
NULL;
<BR> wc.lpszMenuName
= (LPSTR) NULL;
<BR> wc.lpszClassName
= (LPSTR) szUIClassName;
<BR> wc.hbrBackground
= NULL;
<BR> if(!RegisterClass((LPWNDCLASS)&wc))
<BR> return
FALSE;
<BR> wc.style =
CS_MYCLASSFLAG | CS_IME;
<BR> wc.lpfnWndProc
= MyCompStringWndProc;
<BR> wc.cbClsExtra
= 0;
<BR> wc.cbWndExtra
= cbMyWndExtra;
<BR> wc.hInstance
= hInst;
<BR> wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
<BR> wc.hIcon =
NULL;
<BR> wc.lpszMenuName
= (LPSTR) NULL;
<BR> wc.lpszClassName
= (LPSTR) szUICompStringClassName;
<BR> wc.hbrBackground
= NULL;
<BR> if(!RegisterClass((LPWNDCLASS)&wc))
<BR> return
FALSE;
<BR> break;
<BR> case
DLL_PROCESS_DETACH:
<BR> UnregisterClass(szUIClassName,hInst);
<BR> UnregisterClass(szUICompStringClassName,hInst);
<BR> break;
<BR> }
<BR> return TRUE; <BR>} <BR><BR>5、UI窗口
<BR> IME類對(duì)應(yīng)的IME窗口被應(yīng)用程序或者系統(tǒng)創(chuàng)建,當(dāng)IME窗口被創(chuàng)建時(shí),IME自身提供的UI窗口被創(chuàng)建并被IME窗口所擁有。每一個(gè)UI窗口有一個(gè)當(dāng)前的輸入上下文,當(dāng)UI窗口接收到IME消息(WM_IME_*)時(shí),可以通過(guò)調(diào)用GetWindowLong函數(shù)和指定IMMGWL_IMC索引值查找到輸入上下文,UI窗口可以根據(jù)輸入上下文處理消息,UI窗口可以在除響應(yīng)WM_CREATE消息以外的任何時(shí)間查找到輸入上下文。
<BR> IME不允許改變UI窗口的窗口附加數(shù)據(jù),如果UI窗口的某個(gè)實(shí)例需要窗口附加數(shù)據(jù),可以使用IMMGWL_PRIVATE參數(shù)值調(diào)用SetWindowLong和GetWindowLong函數(shù),IMMGWL_PRIVATE參數(shù)值提供為UI窗口的某個(gè)實(shí)例存取附加數(shù)據(jù)中LONG類型值的能力,如果需要大于LONG類型值的附加數(shù)據(jù),可以保存一個(gè)內(nèi)存塊的句柄到IMMGWL_PRIVATE域。
<BR> UI窗口過(guò)程可以使用DefWindowProc函數(shù),但是UI窗口不允許傳遞IME消息給DefWindowProc函數(shù),即使某個(gè)IME消息沒(méi)有被處理,UI窗口也不允許傳遞該消息給DefWindowProc函數(shù)。
<BR>LRESULT UIWndProc (HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam) <BR>{ <BR>HIMC hIMC; <BR>HGLOBAL hMyExtra;
<BR>switch(msg){ <BR>case WM_CREATE: <BR>// Allocate the
memory bloack for the window instance. <BR>hMyExtra =
GlobalAlloc(GHND,size_of_MyExtra); <BR>if (!hMyExtra)
<BR>MyError(); <BR>// Set the memory handle into
IMMGWL_PRIVATE <BR>SetWindowLong(hWnd, IMMGWL_PRIVATE,
(LONG)hMyExtra); <BR>. <BR>. <BR>. <BR>break; <BR>case
WM_IME_xxxx: <BR>// Get IMC; <BR>hIMC =
GetWindowLong(hWnd,IMMGWL_IMC); <BR>// Get the memory handle
for the window instance. <BR>hMyExtra = GetWindowLong(hWnd,
IMMGWL_PRIVATE); <BR>lpMyExtra = GlobalLock(hMyExtra); <BR>.
<BR>. <BR>. <BR>GlobalUnlock(hMyExtra); <BR>break; <BR>. <BR>.
<BR>. <BR>case WM_DESTROY: <BR>// Get the memory handle for
the window instance. <BR>hMyExtra = GetWindowLong(hWnd,
IMMGWL_PRIVATE); <BR>// Free the memory block for the window
instance. <BR>GlobalFree(hMyExtra); <BR>break; <BR>default:
<BR>return DefWindowProc(hWnd, msg, wParam, lParam); <BR>}
<BR>}
<BR> UI窗口必須在當(dāng)前選定的輸入上下文中執(zhí)行動(dòng)作,當(dāng)一個(gè)窗口被激活時(shí),UI窗口接收到提供當(dāng)前輸入上下文的消息,此后,UI窗口運(yùn)行在當(dāng)前選中的輸入上下文上。輸入上下文必須包括UI窗口顯示寫(xiě)作窗口、狀態(tài)窗口等需要的所有信息。
<BR> UI窗口要求輸入上下文,但是窗口不必自己更新輸入上下文。當(dāng)UI窗口需要更新輸入上下文時(shí),應(yīng)該調(diào)用IMM函數(shù),因?yàn)檩斎肷舷挛挠蒊MM函數(shù)管理,當(dāng)輸入上下文更新時(shí),IMM和IME接收到通知消息。
<BR> 例如,有時(shí)UI窗口當(dāng)鼠標(biāo)單擊時(shí)需要改變輸入上下文的轉(zhuǎn)換模式,為了設(shè)置轉(zhuǎn)換模式,UI窗口調(diào)用ImmSetConversionMode函數(shù),該函數(shù)為NotifyIME生成一個(gè)通知消息并發(fā)送WM_IME_NOTIFY消息到UI窗口,如果UI窗口改變轉(zhuǎn)換模式的顯示,UI窗口會(huì)等待處理WM_IME_NOTIFY消息。
<BR><BR>6、UI窗口的部件
<BR> UI窗口可以根據(jù)輸入上下文注冊(cè)和顯示寫(xiě)作窗口和狀態(tài)窗口,UI窗口的部件類的窗口風(fēng)格必須包括CS_IME。UI窗口的一個(gè)窗口實(shí)例從當(dāng)前輸入上下文接收例如寫(xiě)作字符串、字體、位置等信息,當(dāng)應(yīng)用程序的一個(gè)窗口獲得焦點(diǎn)時(shí),系統(tǒng)獲取該窗口自己的輸入上下文并將當(dāng)前輸入上下文傳遞給UI窗口,系統(tǒng)發(fā)送WM_IME_SETCONTEXT消息和輸入上下文的句柄給應(yīng)用程序,應(yīng)用程序傳遞該消息給UI窗口。如果當(dāng)前輸入上下文被更新,UI窗口應(yīng)該重新繪制寫(xiě)作窗口,無(wú)論何時(shí)輸入上下文改變,UI窗口都應(yīng)該顯示正確的寫(xiě)作窗口,可以保證IME的狀態(tài)。
<BR> UI窗口可以創(chuàng)建子窗口或者彈出式窗口顯示狀態(tài)、寫(xiě)作字符串或者候選字列表,這些窗口必須是UI窗口的附屬窗口,而且必須創(chuàng)建為不可接收輸入(Disable)窗口,任何IME創(chuàng)建的窗口都不應(yīng)該獲取焦點(diǎn)。
<BR><BR>三、輸入上下文 <BR><BR>1、缺省輸入上下文
<BR> 缺省情況下系統(tǒng)給每個(gè)線程一個(gè)輸入上下文,該輸入上下文被線程的所有無(wú)IME支持窗口共享。
<BR><BR>2、輸入上下文與窗口的交互
<BR> 應(yīng)用程序的一個(gè)窗口可以使用窗口句柄與輸入上下文交互以維護(hù)任何IME狀態(tài),包括中間寫(xiě)作字符串。一旦應(yīng)用程序使得輸入上下文與窗口句柄交互,無(wú)論何時(shí)窗口被激活,系統(tǒng)自動(dòng)選中輸入上下文。使用這個(gè)特點(diǎn),應(yīng)用程序可以輕松地完成Windows
3.1下必須的復(fù)雜切換處理。 <BR><BR>3、使用輸入上下文
<BR> 當(dāng)應(yīng)用程序或者系統(tǒng)創(chuàng)建新的輸入上下文時(shí),系統(tǒng)準(zhǔn)備新的輸入上下文,新的輸入上下文已經(jīng)包括IMCC,這個(gè)IMC的部件由hCompStr、hCandInfo、hGuideLine、hPrivate和hMsgBuf組成。IME基本上不需要?jiǎng)?chuàng)建輸入上下文和輸入上下文的部件,不過(guò)IME可以改變它們的大小,可以通過(guò)鎖定它們查找到部件的指針。
<BR> <BR>⑴存取HIMC
<BR> 為了存取輸入上下文,IME必須調(diào)用ImmLockIMC函數(shù)以查找到輸入上下文的指針,ImmLockIMC函數(shù)給IMC增加imm鎖定計(jì)數(shù),ImmUnlockIMC函數(shù)減少之。<BR><BR>⑵存取HIMCC
<BR> 為了存取輸入上下文中的一個(gè)部件,IME必須調(diào)用ImmLockIMCC函數(shù)獲取IMCC的指針,ImmLockIMCC函數(shù)給IMCC增加imm鎖定計(jì)數(shù),ImmUnlockIMCC函數(shù)減少之,ImmReSizeIMCC函數(shù)可以修改IMCC的大小以指定新的大小。
<BR> 某些情況下,IME可能需要自己創(chuàng)建輸入上下文的一個(gè)部件,這種情況下,IME可以調(diào)用ImmCreateIMCC函數(shù)獲取IMCC的句柄,這個(gè)IMCC可以是INPUTCONTEXT結(jié)構(gòu)的成員(hCompStr、hCandInfo、hGuideLine、hPrivate或者h(yuǎn)MsgBuf)。
<BR> ImmDestroyIMCC清除輸入上下文的一個(gè)部件。
<BR><BR>⑶怎樣使用輸入上下文
<BR> 下面的實(shí)例顯示了怎樣使用輸入上下文
<BR>LPINPUTCONTEXT lpIMC; <BR>LPCOMOSITIONSTRING lpCompStr;
<BR>HIMCC hMyCompStr; <BR>if (hIMC) { // It is not NULL
context. <BR>lpIMC = ImmLockIMC(hIMC); <BR>if (!lpIMC) {
<BR>MyError( "Can not lock hIMC"); <BR>return FALSE; <BR>}
<BR>// Use lpIMC->hCompStr. <BR>lpCompStr =
(LPCOMPOSITIONSTRING) ImmLockIMCC(lpIMC->hCompStr); <BR>//
Access lpCompStr. <BR>ImmUnlockIMCC(lpIMC->hCompStr);
<BR>// ReSize lpIMC->hCompStr. <BR>if (!(hMyCompStr =
ImmReSizeIMCC(lpIMC->hCompStr,dwNewSize)) {
<BR>MyError("Can not resize hCompStr");
<BR>ImmUnlockIMC(hIMC); <BR>return FALSE; <BR>}
<BR>lpIMC->hCompStr = hMyCompStr; <BR>ImmUnlockIMC(hIMC);
<BR>} <BR><BR>四、生成消息
<BR> IME需要生成IME消息。當(dāng)IME開(kāi)始轉(zhuǎn)換時(shí),IME必須生成WM_IME_STARTCOMPOSITION消息,如果IME改變了寫(xiě)作字符串,IME必須生成WM_IME_COMPOSITION消息,IME引發(fā)的事件導(dǎo)致生成消息給與輸入上下文進(jìn)行交互的窗口。IME基本上使用ImeToAsciiEx函數(shù)參數(shù)提供的lpdwTransKey緩沖區(qū)生成消息,當(dāng)ImeToAsciiEx函數(shù)被調(diào)用時(shí)IME存儲(chǔ)消息到lpdwTransKey緩沖區(qū)中,不過(guò)即使ImeToAsciiEx函數(shù)沒(méi)有
<BR>被調(diào)用,IME也可以生成消息給使用輸入上下文的消息緩沖區(qū)與輸入上下文交互的窗口。輸入上下文有一個(gè)內(nèi)存塊的句柄作為消息緩沖區(qū),IME存儲(chǔ)消息到被消息緩沖區(qū)句柄提供的內(nèi)存塊中,以后IME調(diào)用ImmGenerateMessage函數(shù),ImmGenerateMessage函數(shù)發(fā)送保存在消息緩沖區(qū)中的消息到適當(dāng)?shù)拇翱凇?lt;BR><BR>1、在ImeToAsciiEx函數(shù)中使用消息緩沖區(qū)
<BR> 下面的實(shí)例顯示了怎樣通過(guò)傳遞緩沖區(qū)到ImeToAsciiEx函數(shù)生成消息:
<BR>UINT ImeToAsciiEx(uVirKey, uScanCode, lpbKeyState,
lpdwTransBuf, <BR>fuState , hIMC ) <BR>{ <BR>DWORD dwMyNumMsg
= 0; <BR>. <BR>. <BR>. <BR>// Set the messages that the IME
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -