如何初識
WINDOWSc++
下編程
IMEwindows
編程數組
IME數據結構
編程心得架構
第一章app
Windows9x框架
系統下漢字輸入法的基本原理編輯器
第二章ide
Windows9x
系統提供的
ime
管理函數
第三章
ime
文件中必須使用的結構
自由拼音輸入法的測試
輸入法程序
[ime]
的調試方法
輸入法
(IME)
實現原理 你們知道,
DELPHI
許多控件有
IME
屬性。這麼好用的東西
VC
可沒自帶,怎麼辦呢?其
實,可經過註冊表,用
API
實現。下面說一下本人對
IME
的研究結果,並提供示例工程供
你們參考
:
1
、將用到的
API
Cpp
代碼
:打開註冊表一鍵
:查詢一鍵值
:同上
:關閉打開的鍵
LoadKeyboardLayout
:裝載輸入法
:激活輸入法
2
、
IME
信息在註冊表中的位置
在
HKEY_USERS:".DEFAULT\keyboard layout\preload"
放的是已安裝的輸入法,下有幾
個以數字爲名的子鍵,內容是輸入法代號
(keyboard layout)
,如
"e0040804",
其中左
4
位是
設備代碼
(device identifier)
,右
4
位是語言代碼
(language identifier)
。例如上面:左
e004
指智能
ABC,
右
0804
指大陸中文。
(
詳見
MSDN) 在
HKEY_LOCAL_MACHINE:"System\CurrentControlSet\Control\Keyboard Layouts"
放
的是已註冊的輸入法。他的子鍵名爲輸入法代號
(keyboard layout)
,內容爲該輸入法的
ime
文件,名稱等信息。
3
、主要思路
咱們可先把已裝的輸入法枚舉出來
(
從註冊表
)
,用戶選擇其一後,再激活該輸入法。
兩關鍵函數:
HKL LoadKeyboardLayout(LPCTSTR pwszKLID,UINT Flags);
第一個參數是待打開的輸入法代號,如
"e0040804"(
智能
ABC);
第二個參數是標誌位,如
KLF_ACTIVATE(
激活
)
。
HKL ActivateKeyboardLayout(HKL hkl,UINT Flags);
第一個參數是打開的輸入法句柄
(
由
LoadKeyboardLayout
返回
);
第二個參數是標誌位,如
KLF_SETFORPROCESS
。
(
詳見
MSDN)
4
、例子程序
新建一基於對話框的工程,加入一
combobox
控件,增長控制變量
m_cb1
。加入一
edit
控
件,增長控制變量
m_edt1.
對
combobox,
增長對
CBN_SELCHANGE
的映射函數
OnSelchangeCombo1()
。對
edit1
,增長對
EN_SETFOCUOS
的
SetfocusEdit1().
在對話
框類頭文件的
public:
下加入數組聲明:
CString lst[10];
在
OnInitDialog()
的
return
前加以下代碼:
Cpp
代碼
HKEY
hk,hk1;
long
cp=16;
char
lp[15];
char
a[2];
a[0]='1';
a[1]='\0';
CString str,str1;
已裝的輸入法。注:
win2000
有所不
同
str+=a;
int
i=0;
打開鍵
{
a[0]++;//
下一子鍵
str=".DEFAULT\\keyboard layout\\preload\\";
str+=a;
if(::RegQueryValue(hk,NULL,lp,&cp)!=ERROR_SUCCESS)//
已裝的輸入法
MessageBox("Error");
::RegEnumKeyEx
str1="System\\CurrentControlSet\\Control\\Keyboard Layouts\\";//keyboardlay
outLayout
str1+=lp;
lst[i++]=lp;
//
打開對應的
keyboardlayoutLayout
if(RegOpenKey(HKEY_LOCAL_MACHINE,str1,&hk1)==ERROR_SUCCESS
)
{
LPBYTE
lpD=new
BYTE
[80];//DataValue
DWORD
lpT=REG_SZ;//DataType
DWORD
lpS=80; //DataSize
if(RegQueryValueEx(hk1,"Layout text",NULL,&lpT,lpD,&lpS)!=ERROR_SUC
CESS)
MessageBox("Query error",(
LPCTSTR
)lpD);
m_cb1.AddString((
LPCTSTR
)lpD);
delete lpD;
}
else MessageBox("open error");
RegCloseKey(hk1);
}
::RegCloseKey(hk);
m_cb1.SetCurSel(0);
在
OnSetfocusEdit1()
加入以下代碼:
Cpp
代碼
CString temp;
temp=m_cb1.GetCurSel()!=CB_ERR?st[m_cb1.GetCurSel()]:"00000409";
HKL
hkl;
裝載輸入法
if(hkl==NULL) OnOK();
激活輸入法
在
OnSelchangeCombo1()
加入以下代碼:
Cpp
代碼
便可編譯運行。
5
、注意:
win2000
下有所不一樣。註冊表
HKEY_USERS:".DEFAULT\keyboard
layout\preload
沒有子鍵只有以數字爲名的項,值爲輸入法代號
(keyboard layout)
。在示例
代碼中不只提供了
WIN 9X
下的代碼,也提供了
2000
下的相應代碼段,具體請參考示例
工程。
IME
編程心得
1、基礎知識
:(
不斷補充
)
輸入法管理器
(IMM)
輸入法編程器
(IME)
輸入上下文
(IC)
應用程序
(App)
2、
IMM-IME
結構的基本工做過程及特色
用戶鍵盤消息
->
系統經過
IMM
傳遞給與當前線程對應的
IME->IME
根據輸入的消息和輸入
上下文中記錄的數據,將用戶的鍵盤動做轉換成結果串
->
以字串消息的形式返回給
IMM->
放到應用程序窗口的消息隊列中。
3、
IME
的構成
1.IME
轉換接口
(IME conversion interface)
2.IME
用戶接口
(IME user interface)
由用戶實現的一組窗口
,
這些窗口用來接收和處理由
IMM
發來的輸入消息
,
提供與用戶交互
的界面
.
由下面的窗口組成
:
缺省的
IME
窗口
(Default IME window)
用戶接口窗口
(UI interface)
用戶接口窗口的組件
:
狀態窗口
(status window);
編碼窗口
(compsition window);
候選窗口
(candidate window).
軟鍵盤和系統菜單
/
圖標等
4、
IME
的實現
1.IME
轉換接口的實現
這些接口函數在供管理器在適當的時候調用
.
這些函數並不是每一個都要進行本身的處理
,
大部
分保留一個空函數便可
,
但沒有卻不可
.
系統默認是要調用的
,
找不到就不行
.
有如下函數
:
1)ImeInquire
2)ImeConfigure
3)ImeProcessKey
4)ImeToAsciiEx
5)ImeSelect
6)ImeSetActiveContext
7)NotifyIME
8)ImeDestroy
9)ImeConversionList
10)ImeEscape
11)ImeSetCompsitionString
12)ImeRegisterWord
13)ImeUnregisterWord
14)ImeGetRegisterWordStyle
15)ImeEnumRegisterWord
2.IME
用戶接口的實現
主要包括用戶接口窗口
(
窗口類和窗口過程
),
用戶界面窗口的組件
(
狀態窗口
,
編碼窗口和候
選窗口的窗口類和窗口過程
),
輸入法的配置窗口
,
軟鍵盤
,
任務條上的指示器窗口
(
圖標
,
菜單
,
工具提示
)
和輸入法熱鍵等
.
用戶接口窗口
:
編程中主要是處理由缺省的
IME
窗口傳入的
IME
消息
,
固然
,
並不是全部的
IME
消息都須要給出具體處理
(
能夠看出這是
IME
編程中的一個原則
).
如
:
WM_IME_COMPOSITION
WM_IME_STARTCOMPSITION/WM_IME_ENDCOMPOSITION
WM_IME_SELECT
WM_IME_NOTIFY
WM_IME_CHAR
5、具體實現步驟:
IME
實質上是一個
DLL
實現,由系統調用。而這個
DLL
則分別實現了系統要調用的功能
函數。因此有些函數雖然不作什麼事情,可是必需掛上一個空殼。不然調用出錯。
1.DLLMain()
的架構
進入進程
DLL_PROCESS_ATTACH
事件中,註冊用戶接口窗口類及其組件的窗口類:使用
RegisterClassEx()
完成此註冊過程。設置類名字段
(lpszClassName)
爲用戶接口窗口類類
名(包括結束標誌
'\0'
在內最長可達
16
字符),在類風格
(style)
字段中必須包括
CS_IME
風格。設置附加內存大小(
cbWndExtra
)。
退出進程
註銷上述與輸入法編輯器有關的窗口類,進行全局性的清理工做。
打開
/
關閉輸入法編輯器時進行的初始化操做
用戶接口窗口是由缺省的
IME
窗口在接到
WM_IME_SELECT
消息時建立的。輸入法管
理器經過調用
ImeRequire
接口函數獲取輸入法編輯器的相關信息
(
屬性、用戶接口窗口
類,可選項
)
,據此進行輸入法編輯器的初始化工做,建立輸入法編輯器的用戶接口窗口。
因此
ImeRequire
是輸入法轉換接口必須實現的第一個函數。
在用戶接口窗口被建立後,能夠進行輸入法編輯器全局性的一些初始化工做,好比申請
本身的私有內存,創建私有上下文等,這些工做通常在處理
WM_IME_SELECT
消息或在
接口函數
ImeSelect
中進行,也能夠在窗口過程處理
WM_CREATE
消息時進行。
進入進程後
:
初始化詞庫
建立字體
註冊窗口類
在
UI
窗口創建後
,
創建寫做窗口和候選窗口
各個窗口下進行各自的消息函數處理
在這裏有疑問
:UI
窗口是什麼
?UI
窗口處理了
IME
的好多消息
.--
解答參看
<<
基於
IMM-IME
輸入法接口的實現方法
下一個任務
:
看這個論文
UI
窗口是對用戶不可見的
,
可是它是全部用戶界面窗口的組件窗口的父窗口
,
是所有組件窗
口的管理者
.
構建框架的問題
在
projects-settings-c/c++-catagory:prepossessor:additional include directories:./
避免添加系統默認的頭文件
注意的細節問題
:
1)global.c
中的
#pragma data_seg(".zhenhuadic"),
應詳細瞭解其做用
,
其與
Czh.def
中的定
義有相關聯的地方
.(
對咱們的工程名
Czh
來講
)
2)freepy.exp : warning LNK4070: /OUT:Czh.ime directive in .EXP differs from output
filename;C:\WINDOWS\system32\freepy.ime; ignoring directive
對於這個
BUILD
中的錯誤
,
關聯之處在於
Czh.def
中定義了
lib
的輸出名爲
Czh,
要求這個
lib
的輸出名與
Output file name freepy
相同
.
若是
.ime
名和上述
中說的問題沒有的話
,
且
freepy.h(
原工程
)
中的
#define
FREEPYFILENAME
_T("freepy.ime")
定義正確
,
則在
HZfreepy.h
中改變如下幾個文件名
與
C:\windows\system32(window xp
系統下
)
下的相關文件名相同則可
:
freepy.tab--
字庫
freepysys.dic--
系統詞庫
freepyusr.dic--
用戶詞庫
在
ImeSelect
的函數中
,
有個註冊表鍵值的處理與工程有關聯
有四條消息的遺漏
:
imm:NotifyIME
imm:NotifyIME:NI_CONTEXTUPDATED
imm:NotifyIME:NI_CONTEXTUPDATED:IMC_SETCOMPOSITIONWINDOW
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW
UIWnd:3
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETOPENSTATUS
UIWnd:3
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETCONVERSIONMODE
UIWnd:3
UIWnd
UIWnd:WM_IME_NOTIFY
UIWnd:WM_IME_NOTIFY:IMN_SETSENTENCEMODE
在開發過程當中
,
初始化的四條消息缺漏
.
考察
:
與代碼有關仍是與安裝有關
?
本身開發安裝是手動完成的
,
即經過直接改註冊表來實現的
.
爲了檢測
,
我將本身的開發代碼
工程做以下變更
:
----settings-output file name\freepy.ime
字庫詞庫名不變
,
但存在
system32
目錄下
只要這樣
,
就能夠出現了上述的消息
.
這時還與
ImeSelect
下的註冊表項讀取無關、與
czh.h
中的文件名定義無關、與
czh.def
中的
lib
定義無關。可是在調試時,選擇輸入法時卻可將
本工程的圖標之類的調出來。這樣看來,只是沒法輸入文字(還沒實現相關的功能),目
前的結論是:四個消息的遺漏與安裝有關。
製做安裝程序
:
仿照
freepy
的安裝程序
,
製做一個本身的安裝程序
,
而後從新安裝
,
安裝以後
要進行更新
,
也就是到輸入法的添加刪除界面進行刪除而後再添加進來
,
註銷系統以後
,
就可
以用了
.
這樣安裝的結果是
:
多出了上面的第二條消息
,
其它仍然不行
.--
哪究竟與誰有關係
?
是否是與
代碼有關
?
只要將
,settings
中的做改變就能夠實現消息補充
.
這與什麼有關係
?
再從新安裝一次
,
此次重裝是這樣的
:
--HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Keyboard Layouts\
下對應
的振華輸入法子項都刪除
--HKEY_CURRENT_USER\Keyboard Layout\preload
下對應的本輸入法的子項刪除
--HKEY_LOCAL_MACHINE\software\
下的
czhhua
刪除
.
這樣重裝以後
,
消息出現
.
流程分析
:
字庫的裝載
這個工做是在程序進入
DLL
的開始部分就執行的
,
將字典內容保存到存儲區
,
以備將
COMPSTR
轉成漢字時調用存儲區
.
第一章
Windows9x
系統下漢字輸入法的基本原理
Windows
系統下漢字輸入法其實是將輸入的標準
ascii
字符串按照必定的編碼規則轉換
爲漢字或漢字串,進
入到目的地。
因爲應用程序各不相同,用戶不可能本身去設計轉換程序,所以,漢字輸入天然而然
落到
WINDOWS
系統管理中。
1、輸入法與系統的關係
鍵盤事件
應用程序
|
|
Windows
的
USER.EXE
|
輸入法管理器
|
輸入法
系統的鍵盤事件有
windows
的
user.exe
軟件接收後,
user.exe
在將鍵盤事件傳導輸入法
管理器
(Input Method
Manager,
簡稱
IMM)
中,管理器
再將鍵盤事件傳到輸入法中,輸入法根據用戶編碼字
典,翻譯鍵盤事件爲對
應的漢字
(
或漢字串
)
,
而後再反傳到
user.exe
中,
user.exe
再將翻譯後的鍵盤事件傳
給當前正運行的應用
程序,從而完成漢字的輸入。
2、漢字輸入法的組成
微軟
Windows9x
系統中漢字輸入法的名稱是
"Input Method Editor" ,
簡稱
IME,
輸入法的程
序名稱爲
:*.ime,
數據文
件名稱爲
*.MB,
即一般說的輸入法編碼表
(
字典
).
實際上
IME
文件是一個動態鏈接庫程序(
DLL
),它與
dll
文件沒有區別,只是名稱不一樣
而已。
通常漢字輸入法都由三個窗口組成
:
狀態窗口(
Status Windows)-
顯示當前的輸入法狀態(中文仍是英文等站環信息);
編碼輸入窗口
(Composition Windows)-
顯示當前擊鍵狀況;
漢字選擇窗口
(Candidates Windows)-
列出當前編碼的所有漢字
(
串
),
供用戶選擇或查詢。
上述三個窗口由基本的用戶接口(
User Interface
)函數管理着。
如今咱們用
Dumpbin.exe
打開微軟提供的拼音輸入法
(
WINDOWS\SYSTEM\WINPY.IME
)看看它有什麼組成(這裏一
WINDOWS98
爲例,並假定
windows
系統安裝在
c:
盤下):
Cpp
代碼
c:\windows\system\winpy.ime
Microsoft (R) COFF Binary File Dumper Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file WINPY.IME
File Type: DLL
//
IME
實際爲
dll
程序
Section contains the following exports for WINPY.ime
0 characteristics
34A37323 time date stamp Fri Dec 26 17:04:35 1997
0.00 version
1 ordinal base
19 number of functions //
共有19個函數
//
對應19個名稱
ordinal hint RVA name
1 0 0000A010 CandWndProc
//"
選擇漢字窗口
"
註冊函數
//"
輸入編碼窗口
"
註冊函數
//
配置當前
ime
參數函數
將字符或字符串轉換成目標字符
//
退出當前使用的
IME
6 5 000030D0 ImeEnumRegisterWord
7 6 0000FFB0 ImeEscape //
應用軟件訪問輸入法的接口函數
.
8 7 00003080 ImeGetRegisterWordStyle
9 8 0000E9A0 ImeInquire
//
啓動並初始化當前
IME
輸入法
//IME
輸入鍵盤事件管理函數
向輸入法字典註冊字符串
啓動當前
IME
輸入法
設置當前的輸入處於活動狀態
.
由應用程序設置輸入法編碼
//
將輸入的鍵盤事件轉換爲漢字編碼事件
刪除被註冊的字符串
.
//IME
事件管理函數
//
狀態窗口註冊函數
//
用戶界面接口函數
Summary
5000 .ShareDa
7000 .data
2000 .idata
1000 .rdata
3000 .reloc
5000 .rsrc
2000 .sgroup
18000 .text
從上述能夠看出,
IME
程序共有19個出口函數組成,每個函數都有特定的格式,它們
擔負着與
windows
系統傳遞信息的做用,這些函數是供
Windows
系統調用的。
3、輸入法的函數簡介
下面咱們將介紹上述各個函數的功能及接口格式。
Cpp
代碼
BOOL
ImeInquire( //
初始化
IME
lpIMEInfo,
//
用於初始化該輸入法的結構地址
LPTSTR
lpszWndClass, //
當前輸入法的名稱
LPCTSTR
或者
dword lpszData //
系統信息
,9X
系列值爲
0,NT/2000
下有實際值
)
若是該函數初始化成功
,
返回
TURE,
不然爲
FALSE
用戶應該搞清楚
IMEINFO
結構
,
特關係着你設計的輸入法是否成功
.
有關該結構請
看
"
結構
"
一章
.
DWORD
IMEConversionList( //
將某字符或字符串轉換成目標字符串
hIMC,
//
與當前輸入法相關的應用程序句柄
要轉換的字符串
(
也多是結果串
,
可由
uFlag
指定
)
轉換後的字符串
(
也多是源串
,
可由
uFlag
指定
)
DWORD
dwBufLen, //
轉換後有幾個字符
UINT
uFlag //
指定結果的存放位置
)
若是成功
,
返回轉換後的字符串長度
BOOL
ImeConfigure( //
用戶設置輸入法接口
HKL
hKL, //
當前輸入法句柄
HWND
hWnd, //
配置窗口的父窗口
DWORD
dwMode, //
配置什麼
LPVOID
lpData //
用戶設置的數據
)
該函數的功能是提供給輸入法使用者一個能夠更改某些隱含設置的能力
.
若是你用過別人的輸入法
,
其中的
"
配置輸入法
..."
功能既是也
!
對於一個初寫輸入法的人
,
能夠不予理它
.
BOOL
ImeDestroy( //
關閉當前輸入法
UINT
uReserved //
無用
(0)
)
成功返回
TURE,
不然爲
FALSE
LRESULT
ImeEscape( //
用戶軟件訪問輸入法內部信息的接口
當前的應用程序句柄
UINT
uEscape, //
設置函數功能
//=IME_ESC_QUERY _SUPPORT
//=IME_ESC_RESERVED_LAST IME_ESC_RESERVED_FIRST
//=IME_ESC_PRIVATE_FIRST IME_ESC_PRIVATE_LAST
//=IME_ESC_SEQUENCE_TO_ INTERNAL
//=IME_ESC_GET_EUDC_ DICTIONARY
//=IME_ESC_SET_EUDC_ DICTIONARY
//=IME_ESC_MAX_KEY
//=IME_ESC_IME_NAME
//=IME_ESC_SYNC_HOTKEY
//=IME_ESC_HANJA_MODE
//=IME_ESC_GETHELPFILENAME(
只適應
Windows 98
和
Windows 2000)
下不可用
)
LPVOID
lpData //
當前功能所需的數據
)
若是失敗
,
返回
0,
不然有個功能決定
有時
,
人們能夠用此函數懷區輸入法的名稱、幫助文件名稱等。固然,咱們能夠不
提供這些功能。
6
、
BOOL
ImeSetActiveContext( //
激活或擱置當前的輸入法
當前用戶程序句柄
BOOL
fFlag //
激活或擱置:
=TRUE
激活
=FALSE
擱置
)
成功返回
TRUE,
不然爲
FALSE
、
BOOL
ImeProcessKey( //
處理應用程序傳入的全部擊鍵事件,監測是不是當前
輸入法所需的
應用程序句柄
UINT
uVirKey, //
需處理的虛鍵
DWORD
lParam, //
擊鍵消息參數
LPBYTE
lpbKeyState //
當前鍵盤狀態(
256
字節)
)
若是此鍵是該輸入法須要的,則返回
TRUE,
不然爲
FALSE
只有返回
true
的擊鍵,
IME
纔去處理
、
BOOL
NotifyIME( //
輸入法選擇窗口狀態管理函數:
當前的應用程序句柄
DWORD
dwAction, //
狀態值
DWORD
dwIndex, //
與狀態值有關的序號
DWORD
dwValue //
與狀態值有關的值
)
狀態值說明:
打開編碼選擇窗口
關閉當前的編碼選擇窗
選摘編碼
此時:
dwIndex
被選擇的編碼列表序號
.
被選中的編碼在當前的編碼列表中的序號
改變當前的編碼列表(按
pageup
等鍵操做)
此時:
dwIndex
被選擇的編碼列表序號
.
不用
設置編碼開始頁號
此時:
dwIndex
被改變的編碼列表序號
新頁的開始序號
.
改變編碼列表頁的大小
此時:
dwIndex
當前編碼頁序號
新的頁大小
更新應用程序的信息的輸入法的信息:移動位置,設置
模式,設置編碼窗口,字體。
此時:
dwIndex
只用
於
dwValue=IMC_SETCONVERSIONMODE, IMC_SETSENTENCEMODE
可取由
WM_IME_CONTROL
發送的下列值
:
IMC_SETCANDIDATEPOS
IMC_SETCOMPOSITIONFONT
IMC_SETCOMPOSITIONWINDOW
IMC_SETCONVERSIONMODE
IMC_SETSENTENCEMODE
IMC_SETOPENSTATUS
=NI_COMPOSITIONSTR
改變編碼窗口中的編碼
此時:
dwIndex
取下列值:
CPS_COMPLETE
完成編碼轉換
轉換編碼
取消當前的編碼
清除編碼,並關閉編碼窗
不用
此函數成功,返回
TRUE
,不然爲
FALSE
、
BOOL
ImeSelect( //
初始化輸入法
當前應用程序句柄
BOOL
fSelect //
是否初始化當前輸入法,
TRUE
表示初始化
)
返回:成功返回
true
,不然爲
FALSE
The ImeSetCompositionString function is used by an application to set the IME
composition string structure with the data contained in the lpComp or lpRead
parameters. The IME then generates a message.
10
、
BOOL
WINAPI ImeSetCompositionString( //
將編碼窗口中輸入的編碼保存
的編碼結構中,
同志發送編碼完成的消息
(
WM_IME_COMPOSITION
)給系統,
當前的應用程序句柄
DWORD
dwIndex, //
設置此函數功能
//=SCS_SETSTR
//=SCS_CHANGEATTR
//=SCS_CHANGECLAUSE
//= SCS_QUERYRECONVERTSTRING
//=SCS_RECONVERTSTRING
//=SCS_SETRECONVERTSTRING
LPCVOID
lpComp, //
編碼數據區
DWORD
dwCompLen, //
編碼數據區長度
LPCVOID
lpRead, //
讀入的編碼數據
DWORD
dwReadLen //
讀入的編碼數據長度
)
、
UINT
ImeToAsciiEx( //
轉換編碼稱漢字(串)
UINT
uVirKey, //
虛鍵
UINT
uScanCode, //
掃描碼
LPBYTE
lpbKeyState, //
用戶定義的鍵盤狀態
LPDWORD
lpdwTransBuf, //
轉換後的數據存放區
UINT
fuState, //
活動菜單標誌
當前的應用程序句柄
)
返回:返回值表示有幾個消息,可理解爲:本編碼對應的漢字串有幾個漢字組成
(固然,這並不相等)。
、
BOOL
WINAPI ImeRegisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszString
)
13
、
BOOL
WINAPI ImeUnregisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszString
)
14
、
UINT
WINAPI
ImeGetRegisterWordStyle(
UINT
nItem,
LPSTYLEBUF lpStyleBuf
)
15
、
UINT
WINAPI ImeEnumRegisterWord(
hKL,
REGISTERWORDENUMPROC lpfnEnumProc,
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszString,
LPVOID
lpData
)
16
、
DWORD
WINAPI ImeGetImeMenuItems(
HIMC hIMC,
DWORD
dwFlags,
DWORD
dwType,
LPIMEMENUITEMINFO lpImeParentMenu,
LPIMEMENUITEMINFO lpImeMenu,
DWORD
dwSize
四
.ime
的版本信息
(
與普通
DLL
的區別
)
Cpp
代碼
VERSIONINFO
表明字符
含義
4,0,0,950 //4.00.950 95
版
PRODUCTVERSION 4,0,0,950 //4.00.950 95
版
FILEFLAGSMASK 0x3fL
0xaL
FILEOS 0x10004L //VOS_DOS_WINDOWS32 WIN32
軟件
,
可在
DOS
下運行
FILETYPE 0x3L //VFT_DRV
驅動程序
FILESUBTYPE 0xbL //VFT2_DRV_INPUTMETHOD
輸入法驅動程序
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080403a8"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "
唐碼軟件開發工做室
\0"
唐碼輸入法
版本
1.0\0"
VALUE "FileVersion", "4.00.950\0"
VALUE "InternalName", "
唐碼輸入法
版本
1.0\0"
唐碼軟件開發工做室
1999-1999\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "TM.IME\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "
唐碼輸入法
版本
1.0\0"
VALUE "ProductVersion", "4.00.950\0"
VALUE "SpecialBuild", "\0"
END
第二章
Windows9x
系統提供的
ime
管理函數
上一章
,
咱們介紹了
ime
文件中必須設計的函數
,
這些函數要靠咱們本身來設計。要完成這
些函數的設計,
需用到
windows
系統提供的管理函數
(Input Method Manager,
簡稱
IMM)
。
IMM
函數能夠被
IME
函數使用,也可用於應用軟件直接管理
IME
。
相關術語:
(1)input method context
簡稱
IMC--
輸入法相關部分,在這裏解釋爲:相關連的應用程序
(進程)
(2)component of the input context
簡稱
IMCC--IMC
的部件,是
INPUTCONTEXT
結構的
成員。
1、
IME
中使用的
IMM
函數清單
Cpp
代碼
//
取編碼窗口信息
//
設置編碼窗口信息
//
取選擇窗口信息
//
設置選擇窗口信息
//
取編碼窗口的某一信息
//
設置編碼窗口的某一信息
//
取編碼字體
//
設置編碼字體
//
取選擇區中編碼數
取選擇區中編碼
ImmGetGuideLine
ImmGetConversionStatus //
取當前輸入法的狀態(
ACSII,SHAPE,FULL
等)
從新得到選擇區轉換表
取輸入法打開屬性
設置輸入法狀態
設置輸入法打開狀態
通報
IME
,輸入法狀態被改變
將咱們的漢字串法發送到與當前輸入法相關聯的應用軟件
中
嚮應用程序發送
WM_IME_REQUEST
獲取當前
IMC
的
INPUTCONTEXT
結構信息,增長
IMC
計數器
釋放
IMC
計數器
取計數器值
建立
INPUTCONTEXT
結構的一個成員
刪除
IMC
成員緩衝區
取
IMCC
緩衝地址,同時使
IMCC
的計數器值增長
遞減
IMCC
計數器
從新設置
IMC
的成員的緩衝區大小
取
IMC
成員的緩衝區大小
返回
IMC
計數器值
取輸入法狀態鍵,該函數供控制面板使用
設置輸入法的熱鍵
產生一個軟鍵盤
銷燬軟鍵盤
顯示或隱藏軟鍵盤
2、
IMM
函數使用格式說明
Cpp
代碼
、
BOOL
WINAPI ImmGenerateMessage( //
將咱們的漢字串法發送到與當前輸入
法相關聯的應用軟件中
HIMC hIMC //
與當前輸入法相關聯的應用軟件的句柄,
該結構的
hMsgBuf
項即爲漢字串消息
)
成功爲
TRUE
,不然爲
FALSE
、
LRESULT
WINAPI ImmRequestMessage( //
嚮應用程序發送
WM_IME_REQUEST
只是用於
w98
及
w2000
hIMC,
//
與當前輸入法相關聯的應用軟件的句柄
WPARAM
wParam, //
與
WM_IME_REQUEST
相關的
wP
LPARAM
lParam //
與
WM_IME_REQUEST
相關的
LP
//=IMR_COMPOSITIONWINOW
//=IMR_CANDIDATEWINDOW
//=IMR_COMPOSITIONFONT
//=IMR_RECONVERTSTRING
//=IMR_CONFIRMRECONVERTSTRING
//=IMR_QUERYCHARPOSITION
//=IMR_DOCUMENTFEED
)
3
、
LPINPUTCONTEXT WINAPI ImmLockIMC( //
獲取當前
IMC
的
INPUTCONTEXT
結構信息,增長
IMC
計數器
當前應用程序句柄
)
成功返回
INPUTCONTEXT
結構指針,不然爲
NULL
、
BOOL
WINAPI ImmUnlockIMC( //
釋放
IMC
計數器
當前應用程序句柄
)
返回
:
若是
IMC
計數器被減小到
0
了
,
返回
FALSE,
不然爲
TRUE.
注意
:ImmLockIMC
與
ImmUnlockIMC
必須成對出現
,
必須是相同的
HIMC
、
HIMCC WINAPI ImmGetIMCLockCount( //
取計數器值
當前應用程序句柄
)
若是成功返回
HIMC
的計數器值,不然爲
NULL.
、
HIMCC WINAPI ImmCreateIMCC( //
建立
INPUTCONTEXT
結構的一個成員
DWORD
dwSize //
成員的緩衝區長度
)
若是成功返回
IMC
的成員句柄,不然爲
NULL
、
HIMCC WINAPI ImmDestroyIMCC( //
刪除
IMC
成員緩衝區
被刪除的
IMC
的成員
)
若是成功返回
NULL
,不然等於該
HIMCC.
、
LPVOID
WINAPI ImmLockIMCC( //
取
IMCC
緩衝地址,同時使
IMCC
的計數
器值增長
成員句柄
)
If the function is successful, the return value is the pointer for the IMC component
.
Otherwise, the return value is NULL.
9
、
BOOL
WINAPI ImmUnlockIMCC( //
遞減
IMCC
計數器
成員句柄
)
若是
IMCC
的計數器值爲零,則返回
FALSE
,不然爲
TRUE.
、
HIMCC WINAPI ImmReSizeIMCC( //
從新設置
IMC
的成員的緩衝區大小
的成員句柄
DWORD
dwSize //
新緩衝區大小
)
若是成功,返回新的
HIMCC
,不然爲
NULL.
、
DWORD
WINAPI ImmGetIMCCSize( //
取
IMC
成員的緩衝區大小
成員句柄
)
返回
IMC
成員的緩衝區大小
、
DWORD
WINAPI ImmGetIMCCLockCount( //
返回
IMC
計數器值
成員的句柄
)
成功返回該
IMCC
的計數器值,不然爲
0
、
BOOL
WINAPI ImmGetHotKey( //
取輸入法狀態鍵,該函數供控制面板使用
DWORD
dwHotKeyID,
LPUINT lpuModifiers,
LPUINT lpuVKey,
LPHKL lphKL
)
14
、
BOOL
WINAPI ImmSetHotKey( //
設置輸入法的熱鍵
DWORD
dwHotKeyID,
UINT
uModifiers,
UINT
uVKey,
hKL hKL
)
15
、
HWND
WINAPI ImmCreateSoftKeyboard( //
產生一個軟鍵盤
UINT
uType, //
軟件盤上的鍵碼含義的定義方式
//=SOFTKEYBOARD_TYPE_T1
//=SOFTKEYBOARD_TYPE_C1
UINT
hOwner, //
該輸入法的
UI
窗口
int
x, //
定位座標
int
y //
定位座標
)
成功返回軟鍵盤的窗口句柄
、
BOOL
WINAPI ImmDestroySoftKeyboard( //
銷燬軟鍵盤
HWND
hSoftKbdWnd //
軟年盤窗口句柄
)
成功爲
TRUE,
法哦則爲
FALSE.
、
BOOL
WINAPI ImmShowSoftKeyboard( //
顯示或隱藏軟鍵盤
HWND
hSoftKbdWnd, //
軟年盤窗口句柄
int
nCmdShow //
窗口狀態
=SW_HIDE
表示隱藏,
=SW_SHOWNOACTIVATE
表
示顯示
)
如構成功返回
TRUE.
不然爲
FALSE.
第三章
ime
文件中必須使用的結構
前二章咱們講述了
ime
和
imm
函數
,
兩者之間是靠下列結構通信的。
Cpp
代碼
、
IMEINFO
struct tagIMEInfo { //
輸入法的接口信息
用於
ImeInquire
函數中
DWORD
dwPrivateDataSize;//
用戶設計的數據結構的字節數
DWORD
fdwProperty; //
輸入法對鍵盤事件的相應特性
其中其高字可爲下列字節位的組合:
轉換窗口是否放置在需插入字符的位置
該輸入法具備特殊用戶接口
輸入法的選擇窗口中漢字串的起始
序號爲
1
支持
UNICODE
字符
其中其低字可爲下列字節位的組合:
//=IME_PROP_END_UNLOAD
//=IME_PROP_KBD_CHAR_FIRST
首先由鍵盤轉換字符
將
ALT
鍵盤事件傳送到
IME
輸入法內
禁止上位鍵事件進入輸入法內
當關閉輸入法時,完成編碼的轉
換
用於
W98
及
2000
中
DWORD
fdwConversionCaps;//
當前輸入法具備的功能特性
,
若有軟鍵、標點、中
西文切換等功能
設置活動模式
設置全角模式
設置爲字符模式
設置軟鍵盤模式
不支持模式變換
//=IME_CMODE_EUDC //
//=IME_CMODE_SYMBOL //
設置標點字符模式
DWORD
fdwSentenceCaps; //
//=IME_SMODE_PLAURALCLAUSE
//=IME_SMODE_SINGLECONVERT
//=IME_SMODE_AUTOMETIC
//=IME_SMODE_CONVERSATION
DWORD
fdwUICaps; //
用戶界面能力:支持軟鍵盤等
//=UI_CAP_2700
//=UI_CAP_ROT90
//=UI_CAP_ROTANY
//=UI_CAP_SOFKBD
DWORD
fdwSCSCaps; //
用戶設置編碼串的能力
//=SCS_CAP_COMPSTR
//=SCS_CAP_MAKEREAD
DWORD
fdwSelectCaps; //
輸入法切換時是否使用之前輸入法的模式
//=SELECT_CAP_CONVMODE
//=SELECT_CAP_SENTENCE
} IIMEINFO;
2
、
COMPOSITIONSTR
用於編碼管理
用於存放編碼信息的信息
:
全部的實際信
息放在本結構的後面
DWORD
dwSize; //
當前編碼信息須要的存儲空間
=
讀入的編碼
屬性
子串
屬性
編碼
屬性
結果
屬性
DWORD
dwCompReadAttrLen; //
讀入的編碼屬性長度
DWORD
dwCompReadAttrOffset; //
存放在內存的位置
DWORD
dwCompReadClsLen; //
讀入的子串長度
DWORD
dwCompReadClsOffset; //
存放在內存的位置
DWORD
dwCompReadStrLen; //
讀入的編碼長度
DWORD
dwCompReadStrOffset; //
存放在內存的位置
DWORD
dwCompAttrLen; //
編碼屬性長度
DWORD
dwCompAttrOffset; //
存放在內存的位置
DWORD
dwCompClsLen; //
編碼子串長度
DWORD
dwCompClsOffset; //
存放在內存的位置
DWORD
dwCompStrLen; //
編碼串長度
DWORD
dwCompStrOffset; //
存放在內存的位置
DWORD
dwCursorPos; //
當前光標位置
DWORD
dwDeltaStart; //
被修改編碼的位置
DWORD
dwResultReadClsLen; //
讀入結果子串長度
DWORD
dwResultReadClsOffset; //
存放在內存的位置
DWORD
dwResultReadStrLen; //
讀入的編碼長度
DWORD
dwResultReadStrOffset; //
存放在內存的位置
DWORD
dwResultClsLen; //
結果子串長度
DWORD
dwResultClsOffset; //
存放在內存的位置
DWORD
dwResultStrLen; //
結果串長度
DWORD
dwResultStrOffset; //
存放在內存的位置
DWORD
dwPrivateSize; //
用戶自定義數據長度
DWORD
dwPrivateOffset; //
存放在內存的位置
} COMPOSITIONSTR;
3
、
CANDIDATEINFO
用於編碼選擇管理
編碼選擇信息的信息,其後爲實際編碼列
表數據
DWORD
dwSize; //
數據所佔內存大小
DWORD
dwCount; //
表馬列表個數
DWORD
dwOffset[32]; //
各個編碼列表的內存位置
DWORD
dwPrivateSize; //
自定義數據尺寸
DWORD
dwPrivateOffset; //
緩衝區位置
} CANDIDATEINFO;
4
、
GUIDELINE
typedef struct tagGUIDELINE {
DWORD
dwSize;
DWORD
dwLevel; // the error level.
// GL_LEVEL_NOGUIDELINE,
// GL_LEVEL_FATAL,
// GL_LEVEL_ERROR,
// GL_LEVEL_WARNNING,
// GL_LEVEL_INFORMATION
DWORD
dwIndex; // GL_ID_NODICTIONARY and so on.
DWORD
dwStrLen; // Error Strings, if this is 0, there
// is no error string.
DWORD
dwStrOffset;
DWORD
dwPrivateSize;
DWORD
dwPrivateOffset;
} GUIDELINE;
5
、
CANDIDATELIST
The CANDIDATELIST structure contains information about a candidate list.
typedef struct tagCANDIDATELIST { //
編碼選擇列表信息
=
〉管理編碼窗口中的列
表信息
DWORD
dwSize; //
用字節表示的內存大小:
=sizeof(CANDIDATELIST)+
選擇字符
數據
DWORD
dwStyle; //
列表串的取值方式
列表數據的格式無定義
讀到什麼數據即爲何數據
,
通常咱們使用該屬性
若是
dwCount=1
,
dwOffset
不是地址,而是實際數據,
表示地址
//=IME_CAND_MEANING
//=IME_CAND_RADICAL
//=IME_CAND_STROKES
DWORD
dwCount; //
當前列表個數
DWORD
dwSelection; //
當前選擇的列表序號
DWORD
dwPageStart; //
在列表窗口中所顯示的列表的起始序號(上下翻頁時
用)
DWORD
dwPageSize; //
一頁顯示的列表個數
DWORD
dwOffset[]; //
列表數據存放區地址:
[
阿
];[
大
]
。。。。
} CANDIDATELIST;
6
、
COMPOSITIONFORM
窗口位置、大小信息:
} RECONVERTSTRING;
11
、
IMEMENUITEMINFO
輸入法菜單結構,
W98/2000
UINT
cbSize;
UINT
fType;
UINT
fState;
UINT
wID;
HBITMAP
hbmpChecked;
HBITMAP
hbmpUnchecked;
DWORD
dwItemData;
TCHAR
szString[48];
HBITMAP
hbmpItem;
}
12
、
INPUTCONTEXT
The INPUTCONTEXT structure is an internal data structure that stores Input
Context data.
typedef struct tagINPUTCONTEXT { //IMC
數據存放區
HWND
hWnd; //
使用該
IMC
的窗口
BOOL
fOpen; //IME
的打開與關閉狀態
狀態窗口的位置
軟鍵盤的位置
DWORD
fdwConversion; //IME
狀態
(
活動、不活動,全角等)
DWORD
fdwSentence; //
編碼方式
union {
LOGFONTA A;
LOGFONTW W;
} lfFont; //
字體
編碼格式結構
列表選擇結構
HIMCC hCompStr; //
HIMCC hCandInfo;
HIMCC hGuideLine
HIMCC hPrivate;
DWORD
dwNumMsgBuf; //
存放在
hMsgBuf
中的消息數
存放的消息,格式:
[
消息
1] [wParam1] [lParam1] {[
消
息
] [wParam2] [lParam2]...
注意
:
咱們輸入的漢字串存放在這裏
DWORD
fdwInit //
系統根據此值來初始本結構相應的信息
初始化
ptStatusWndPos
初始化
fdwConversion
初始化
fdwSentence
初始化
lfFont
初始化
cfCompForm
初始化
ptSoftKbdPos
DWORD
dwReserve[3]; //
未來版本擴展的信息
在
UI
窗口下須要處理下列
windows
消息
.
1
、
WM_IME_SETCONTEXT
激活或休眠輸入法
LRESULT CALLBACK UIWndProc(HWND hUIWnd,UINT uMsg,WPARAM
wParam,LPARAM lParam)
{
:
case WM_IME_SETCONTEXT:
fSet= (BOOL) wParam;
lISCBits = lParam;
}
若是
fSet
爲
TRUE,
系統將激活當前輸入法的某個窗口
(
狀態窗、列表窗等),爲
FALSE
時
休眠當前輸入法
.
其中
lISCBits
中指出對哪一個窗口操做。
數值
含義
ISC_SHOWUICOMPOSITIONWINDOW
顯示編碼窗口
ISC_SHOWUIGUIDWINDOW
顯示信息窗口
ISC_SHOWUICANDIDATEWINDOW
顯示
0
號列表窗口
(ISC_SHOWUICANDIDATEWINDOW << 1)
顯示
1
號列表窗口
.
(ISC_SHOWUICANDIDATEWINDOW << 2)
顯示
2
號列表窗口
.
(ISC_SHOWUICANDIDATEWINDOW << 3)
顯示
3
號列表窗口
.
2
、
WM_IME_CONTROL
管理當前輸入法
wSubMessage= wParam;
受
WM_IME_CONTROL
控制的消息
lpData = (LPVOID) lParam;
對應的數據
其中子消息有下列消息:
1
)
IMC_GETCANDIDATEPOS
獲取列表窗口的位置
.
此時
lParam
傳送的是
CANDIDATEFORM
結構地址。
若是此消息成功返回
0
,不然非零。
一般若是你設計此部分了,返回
0
。不然返回
1
。
2
)
IMC_GETCOMPOSITONFONT
獲取編碼窗口字體結構,
lParam
爲
LOGFONT
結構地址
若是此消息成功返回
0
,不然非零。
一般若是你設計此部分了,返回
0
。不然返回
1
。
3
)
IMC_GETCOMPOSITONWINDOW
獲取編碼窗口位置,
lParam
爲
COMPOSITIONFORM
結構地址。
若是此消息成功返回
0
,不然非零。
一般若是你設計此部分了,返回
0
。不然返回
1
。
4
)
IMC_GETSOFTKBDFONT
獲取軟鍵盤字體。
lParam
字體結構
LOGFONT
地址。
5
)
IMC_GETSOFTKBDPOS
獲取軟鍵盤位置,
lParam = 0;
返回軟鍵盤在屏幕窗口中的座標結構
POINTS
。
6
)
IMC_GETSOFTKBDSUBTYPE
wSubMessage= IMC_GETSOFTKBDSUBTYPE;
注意:
UI
窗口不接受此消息,它的管理函數是
NotifyIME
。
11
)
IMC_SETSOFTKBDDATA
設置軟鍵盤數據,此時
lParam
傳送的是
SOFTKBDDATA
結構地址,用戶設定本身的軟
鍵盤字符。
wSubMessage= IMC_SETSOFTKBDDATA;
lpSoftKbdData= (LPSOFTKBDDATA) lParam;
若是此消息成功返回
0
,不然非零。
注意:
UI
窗口不接受此消息,它的管理函數是
NotifyIME
。
12
)
IMC_SETSOFTKBDSUBTYPE
設置軟鍵盤類型
wSubMessage= IMC_SETSOFTKBDSUBTYPE;
lSubType= lParam;
成功返回
subtype
,不然返回
-1.
注意:
UI
窗口不接受此消息,它的管理函數是
NotifyIME
。
13
)
IMC_SETSOFTKBDFONT
設置軟鍵盤字體,此時
lParam
傳送的是
LOGFONT
結構地址
wSubMessage= IMC_SETSOFTKBDFONT;
lpLogFont= (LPLOGFONT)lParam;
若是此消息成功返回
0
,不然非零。
注意:
UI
窗口不接受此消息,它的管理函數是
NotifyIME
。
14
)
IMC_SETSOFTKBDPOS
設置軟件位置,此時
lParam
傳送的是
POINTS
結構
wSubMessage= IMC_SETSOFTKBDPOS;
ptsPt= (POINTS)lParam;
若是此消息成功返回
0
,不然非零。
15
)
IMC_SETSTATUSWINDOWPOS
設置狀態窗口位置,此時
lParam
傳送的是
POINTS
結構
wSubMessage= IMC_SETSTATUSWINDOWPOS;
ptsPt= (POINTS)lParam;
若是此消息成功返回
0
,不然非零。
3
、
WM_IME_COMPOSITION
當用戶改變了編碼狀態時,發送此消息
WM_IME_COMPOSITION
應用程序能夠經過調用
ImmGetCompositionString
獲取新的編碼狀態。
wChar= wParam;
最後輸入到編碼窗口的
2
字節的
DBCS
字符
lAttribute= lParam;
當前編碼的含義。
lAttribute
可取下列值得組合:
值
含義
GCR_ERRORSTR
修正錯誤
GCR_INFORMATIONSTR
修正信息串
GCS_COMPATTR
修正編碼串屬性
.
GCS_COMPCLAUSE
修正編碼信息
.
GCS_COMPREADATTR
修正讀入串的屬性
GCS_COMPREADCLAUSE
修正讀入串的屬性
.
GCS_COMPREADSTR
修正讀入串。
GCS_COMPSTR
修正當前的編碼
GCS_CURSORPOS
修正當前編碼的光標位置
.
GCS_DELTASTART
修正當前編碼的開始位置
GCS_RESULTCLAUSE
修正結果串的信息
.
GCS_RESULTREADCLAUSE
修正讀入串的信息
.
GCS_RESULTREADSTR
修正讀入串
.
GCS_RESULTSTR
修正編碼結果串
.
CS_INSERTCHAR
在當前位置插入一個字符
CS_NOMOVECARET
替換結果串
4
、
WM_IME_COMPOSITIONFULL
用戶接口窗口不能增長編碼窗口的尺寸時,
ime
用戶接口窗口將發送
WM_IME_COMPOSITIONFULL
消息,可不處理。
wParam = 0
lParam= 0
5
、
WM_IME_ENDCOMPOSITION
當編碼結束時
ime
發送此消息
WM_IME_ENDCOMPOSITION
wParam = 0
lParam= 0
用戶程序能夠接受此消息,以便本身顯示用戶輸入的編碼。
6
、
WM_IME_SELECT
系統發出
WM_IME_SELECT
以便選擇一個新的
ime
。
fSelect= (BOOL)wParam; TRUE
表示新的
IME
已選擇,
FALSE
表示不被選擇或關閉該輸
入法。
hKL= lParam;
系統利用這個消息產生或關閉老的輸入法用戶窗口。
7
、
WM_IME_STARTCOMPOSITION
當用戶開始輸入編碼時,系統當即發送該消息到
IME
中,
IME
打開編碼窗口。
wParam = 0
lParam= 0
8
、
WM_IME_NOTIFY
IME
消息組:
wSubMessage= wParam;
lParam= lParam;
各消息說明:
1
)
IMN_CLOSESTATUSWINDOW
關閉狀態窗口時,系統發送
IMN_CLOSESTATUSWINDOW
消息。
wSubMessage = IMN_CLOSESTATUSWINDOW;
lParam= 0;
當用戶接口窗口接收到此消息時,將關閉狀態窗口。
2
)
IMN_OPENSTATUSWINDOW
產生或打開狀態窗口
wSubMessage = IMN_OPENSTATUSWINDOW;
lParam= 0;
當
ime
接收到此消息時
,
將產生狀態窗口
.
有關狀態串口的信息可用
ImmGetConversionStatus
獲取
,
設置狀態窗口的信息可用
ImmSetConversionStatus.
3
)
IMN_OPENCANDIDATE
打開或產生列表選擇窗口
wSubMessage = IMN_OPENCANDIDATE;
lCandidateList= lParam;
4
)
IMN_CHANGECANDIDATE
更新當前的列表選擇窗口
WM_IME_NOTIFY
wSubMessage = IMN_CHANGECANDIDATE;
lCandidateList= lParam;
5
)
IMN_CLOSECANDIDATE
關閉選擇窗口
wSubMessage = IMN_CLOSECANDIDATE;
lCandidateList= lParam;
UI
窗口接收此消息後
,
將銷燬列表選擇窗口
IMN_SETCONVERSIONMODE
改變輸入法狀態模式管理
wSubMessage = IMN_SETCONVERSIONMODE;
lParam= 0;
IMN_SETOPENSTATUS
設置輸入法狀態
wSubMessage = IMN_SETOPENSTATUS;
lParam= 0;
IMN_SETCANDIDATEPOS
設置列表窗口位置
wSubMessage = IMN_SETCANDIDATEPOS;
lCandidateList= lParam;
Parameters
IMN_SETCOMPOSITIONFONT
設置編碼窗口字體
wSubMessage = IMN_SETCOMPOSITIONFONT;
lParam= 0;
IMN_SETCOMPOSITIONWINDOW
設置編碼窗口
wSubMessage = IMN_SETCOMPOSITIONWINDOW;
lParam= 0;
IMN_GUIDELINE
錯誤信息處理
wSubMessage = IMN_GUIDELINE;
lParam= 0;
IMN_SOFTKBDDESTROYED
關閉軟鍵盤
wSubMessage = IMN_SOFTKBDDESTROYED;
lParam= 0;
自由拼音輸入法的測試
李振春先生寫的自由拼音能夠從下面的網址下載:
項目主頁
http://gforge.osdn.net.cn/projects/freepyce
能夠用:
svn checkout http://gforge.osdn.net.cn/svn/freepyce
得到最新的源碼。
編程源代碼後,生成
DLL
文件:
freepy.dll
。複製它和
library
目錄的
freepy.tab
和
freepysys.dic
文件到
CE
設備的
windows
目錄。
最好的作法,是經過
PB
將上述的三個文件集成到
CE
映像文件中,同時修改註冊表。這
樣將再也不加載微軟輸入法,而加載自由拼音輸入法。
用
ActiveSync
鏈接
CE
設備,用
Remote Register Editor
鏈接系統嵌入式板的註冊表:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\e0010804
修改,
把
Ime File
鍵值從
msimepy.dll
改成
freepy.dll
。
在
CE
設備上打開
Microsoft WordPad
程序,而後選擇輸入法。對自由拼音進行測試
!
注:不能使用
CE
設備上已經運行的程序,如
explorer
,或給桌面文件更名來測試。因爲
系統原本的微軟輸入法仍然存在,它們還在調用的微軟輸入法。
輸入法程序
[ime]
的調試方法
以自由拼音
(freepy3.1)
爲例
第一步:
安裝
freepy3.1
第二步:
a)
若是是
VC6.0
打開
freepy3.1
工程,打開
vc
主菜單的
Project/settings
的
Link
屬性頁
下的
output file name
下
輸入
c:\winnt\system32\freepy.ime,
這是
win2000,
若是是
xp
則多是
c:\windows\system32\freepy.ime
;還要在
Debug
屬性頁下的
Executable for
debug seesion
下輸入
c:\windows\system32\notepad.exe
。
b)
若是是
VS.NET
打開
freepy3.1
工程,項目
->freepy3.1
屬性,進入連接器頁,設置輸入
文件爲
c:\windows\system32\freepy.ime
,而後進入調試頁,將命令設置爲:
c:\windows\system32\notepad.exe
。根據操做系統不一樣可能有別,請作相應修改!
第三步:
設置斷點,而後按
F5
,進行調試,這時候打開任務欄右下腳輸入法裏的自由拼音輸入法就
能夠了。
完成以上幾步,就能夠在記事本里輸入漢字,而後跟蹤輸入法代碼,從中理解各個函數之
間的相互調用順序!
輸入法
(IME)
實現原理
1、實現原理
中文輸入法的組成
微軟
Windows
系統中輸入法由程序(
DLL
)名稱爲:
*.ime
文件和碼錶文件(字典)
名稱爲
*.mb
文件組成。
中文輸入法的界面
http://wjy.hanwenhua.com/images/Projec6.gif
在
Windows
任務欄
「EN
圖標
」
中增長輸入法名稱
這也就是
Setup
程序的關鍵,實際上,能夠利用
Win32Api
函數
ImmInstallIME()
。
該函數的原形是:
HKL ImmInstallIME( LPCTSTR lpszIMEFileName, LPCTSTR lpszLayoutText);
前一個參數
lpszIMEFileName
是
「.ime」
文件的路徑,
Win9x
爲
「\System」
下,
WinNT/2000
爲
「\System32」
下。後一個參數
lpszLayoutText
是輸入法的明稱。如
HKL
MyIme=ImmInstallIME("Windows\system\3jaja.ime","3++
輸入法
");
若是
MyIme
不返回
NULL
,則調用成功。
4.「.ime」
文件的實現
程序中的輸出函數(必須)即文件
「.def」
中的函數,如下爲函數的名稱和原形,部分函數給
出了原函數,
但願對你能有所幫助。
Cpp
代碼
初始化輸入法函數
BOOL
WINAPI ImeInquire(LPIMEINFO lpImeInfo,
LPTSTR
lpszWndCls,
DWORD
lpszOptions)
{
if (!lpImeInfo)
return (FALSE);
lpImeInfo->dwPrivateDataSize = sizeof(PRIVCONTEXT);
lpImeInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST | IME_PROP_CAN
DLIST_START_FROM_1 | IME_PROP_IGNORE_UPKEYS;
lpImeInfo->fdwConversionCaps = IME_CMODE_NATIVE|IME_CMODE_NATI
VE|IME_CMODE_FULLSHAPE|IME_CMODE_CHARCODE | IME_CMODE_SOF
TKBD | IME_CMODE_NOCONVERSION;
lpImeInfo->fdwSentenceCaps = 0;
lpImeInfo->fdwUICaps = UI_CAP_ROT90 | UI_CAP_SOFTKBD;
lpImeInfo->fdwSCSCaps = SCS_CAP_COMPSTR | SCS_CAP_MAKEREAD;
lpImeInfo->fdwSelectCaps = (
DWORD
)0;
lstrcpy(lpszWndCls, (
LPTSTR
)szUIClassName);
return (TRUE);
}
//
自定義漢字編碼格式,未做處理。
DWORD
WINAPI ImeConversionList(HIMC hIMC,
LPCTSTR
lpszSrc,
DWORD
uB
ufLen,
UINT
uFlag)
{
return (0);
}
//
設置輸入法狀態函數,如光標跟隨等
BOOL
WINAPI ImeConfigure(
HKL
hKL,
HWND
hAppWnd,
DWORD
dwMode,
LPV
OID
lpData)
{
switch (dwMode)
{
case IME_CONFIG_GENERAL:
DialogBox(hInst, MAKEINTRESOURCE(SETIME), (
HWND
)hAppWnd, (DLG
PROC)ImeSetDlgProc);
break;
default:
return (FALSE);
break;
}
return (TRUE);
}
//
退出
BOOL
WINAPI ImeDestroy(
UINT
uReserved)
{
if (uReserved)
return (FALSE);
return (TRUE);
}
//
應用接口函數
LRESULT
WINAPI ImeEscape(HIMC hIMC,
UINT
uSubFunc,
LPVOID
lpData)
{
LRESULT
lRet;
switch (uSubFunc)
{
case IME_ESC_QUERY_SUPPORT:
if ( lpData == NULL )
return FALSE;
switch (*(LPUINT)lpData)
{
case IME_ESC_QUERY_SUPPORT:
case IME_ESC_MAX_KEY:
case IME_ESC_IME_NAME:
case IME_ESC_GETHELPFILENAME:
return (TRUE);
case IME_ESC_SEQUENCE_TO_INTERNAL:
case IME_ESC_GET_EUDC_DICTIONARY:
case IME_ESC_SET_EUDC_DICTIONARY:
case IME_INPUTKEYTOSEQUENCE:
return (FALSE);
default:
return (FALSE);
}
break;
case IME_ESC_SEQUENCE_TO_INTERNAL:
case IME_ESC_GET_EUDC_DICTIONARY:
case IME_ESC_SET_EUDC_DICTIONARY:
case IME_INPUTKEYTOSEQUENCE:
return (FALSE);
case IME_ESC_MAX_KEY:
return ((
WORD
) 4);
case IME_ESC_GETHELPFILENAME:
{
TCHAR
szIMEGUDHlpName[MAXSTRLEN];
if (lpData == NULL )
return FALSE;
szIMEGUDHlpName[0] = 0;
GetWindowsDirectory((
LPTSTR
)szIMEGUDHlpName, MAXSTRLEN);
lstrcat((
LPTSTR
)szIMEGUDHlpName, TEXT("file://HELP//3JaJa.hlp"));
lstrcpy((
char
*)lpData, (
char
*)szIMEGUDHlpName);
return TRUE;
}
default:
return (FALSE);
}
return (lRet);
}
//
啓動輸入法設置功能
BOOL
WINAPI ImeSelect(HIMC hIMC,
BOOL
fSelect
)
{
LPINPUTCONTEXT lpIMC;
BOOL
fRet;
if (!hIMC)
return (FALSE);
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC)
return (FALSE);
fRet = Select(hIMC, lpIMC, fSelect);
ImmUnlockIMC(hIMC);
return (fRet);
}
//
設置輸入活動狀態
BOOL
WINAPI ImeSetActiveContext(HIMC hIMC,
BOOL
fOn)
{
if (fOn&&hIMC)
{
LPINPUTCONTEXT lpIMC;
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC)
return (FALSE);
InitContext(lpIMC);
ImmUnlockIMC(hIMC);
}
return (TRUE);
}
//
用戶按鍵處理函數,例如中英文狀態,返回
FALSE
爲英文狀態,按鍵不做處
理。
BOOL
WINAPI ImeProcessKey(HIMC hIMC,
UINT
uVirtKey,
LPARAM
lParam,C
ONST
LPBYTE
lpbKeyState);
//
輸入法編碼字符處理。
BOOL
WINAPI ImeSetCompositionString(HIMC hIMC,
DWORD
dwIndex,
LPVOI
D
lpComp,
DWORD
dwCompLen,
LPVOID
lpRead,
DWORD
dwReadLen);
將用戶按鍵轉換爲漢字編碼
UINT
WINAPI ImeToAsciiEx(
UINT
uVirtKey,
UINT
uScanCode,CONST
LPBYTE
lpbKeyState,LPTRANSMSGLIST lpTransBuf,
UINT
fuState,HIMC hIMC)
//
處理
IME
消息函數
BOOL
WINAPI NotifyIME(HIMC hIMC,
DWORD
dwAction,
DWORD
dwIndex,
DW
ORD
dwValue);
自定義漢字編碼格式,未做處理。
BOOL
WINAPI ImeRegisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
LP
CTSTR
lpszString)
{
return (FALSE);
}
//
自定義漢字編碼格式,未做處理。
BOOL
WINAPI ImeUnregisterWord(
LPCTSTR
lpszReading,
DWORD
dwStyle,
L
PCTSTR
lpszString)
{
return (FALSE);
}
//
自定義漢字編碼格式,未做處理。
UINT
WINAPI ImeGetRegisterWordStyle(
UINT
nItem,LPSTYLEBUF lpStyleBuf)
{
return (FALSE);
}
//
自定義漢字編碼格式,未做處理。
UINT
WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC lpfnRegi
sterWordEnumProc,
LPCTSTR
lpszReading,
DWORD
dwStyle,
LPCTSTR
lpszStr
ing,
LPVOID
lpData)
{
return (FALSE);
}
//UI
窗口過程
LRESULT
CALLBACK UIWndProc(
HWND
hUIWnd,
UINT
uMsg,
WPARAM
w
Param,
LPARAM
lParam)
{
switch (uMsg)
{
case WM_CREATE:
CreateUIWindow(hUIWnd);
break;
case WM_DESTROY:
DestroyUIWindow(hUIWnd);
break;
case WM_IME_STARTCOMPOSITION:
......
}
}
//
狀態窗口過程
LRESULT
CALLBACK StatusWndProc(
HWND
hStatusWnd,
UINT
uMsg,
WPAR
AM
wParam,
LPARAM
lParam);
編碼窗口過程
LRESULT
CALLBACK CompWndProc(
HWND
hCompWnd,
UINT
uMsg,
WPAR
AM
wParam,
LPARAM
lParam);
侯選漢字窗口過程
LRESULT
CALLBACK CandWndProc(
HWND
hCandWnd,
UINT
uMsg,
WPARA
M
wParam,
LPARAM
lParam);
頭文件及連接文件
記得要定義
IMM32.h
及連接文件
IMM32.lib
。至於有關
「 .ime」
程序中必須用到的結構,
你們可參考
MSDN
中的有關文檔。
2、經常使用函數
BOOL WINAPI ImmGenerateMessage( //
將漢字串法發送到與當前輸入法相關聯的應用軟
件中
HIMC hIMC
);//
成功爲
TRUE
,不然爲
FALSE
LRESULT WINAPI ImmRequestMessage( //
嚮應用程序發送
WM_IME_REQUEST
消息
HIMC hIMC, //
與當前輸入法相關聯的應用軟件的句柄
WPARAM wParam, //
與
WM_IME_REQUEST
相關的
wP
LPARAM lParam //
與
WM_IME_REQUEST
相關的
LP
);
LPINPUTCONTEXT WINAPI ImmLockIMC( //
獲取當前
IMC
的
INPUTCONTEXT
結構信
息,增長
IMC
計數器
HIMC hIMC
);//
成功返回
INPUTCONTEXT
結構指針,不然爲
NULL
BOOL WINAPI ImmUnlockIMC( //
釋放
IMC
計數器
HIMC hIMC );//
返回
:
若是
IMC
計數器被減小到
0
了
,
返回
FALSE,
不然爲
TRUE.
注意
:ImmLockIMC
與
ImmUnlockIMC
必須成對出現
,
必須是相同的
HIMC
HIMCC WINAPI ImmGetIMCLockCount( //
取計數器值
HIMC hIMC );//
若是成功返回
HIMC
的計數器值,不然爲
NULL.
HIMCC WINAPI ImmCreateIMCC( //
建立
INPUTCONTEXT
結構的一個成員
DWORD dwSize //
成員的緩衝區長度
);//
若是成功返回
IMC
的成員句柄,不然爲
NULL
HIMCC WINAPI ImmDestroyIMCC( //
刪除
IMC
成員緩衝區
HIMCC hIMCC
);//
若是成功返回
NULL
,不然等於該
HIMCC.
LPVOID WINAPI ImmLockIMCC( //
取
IMCC
緩衝地址,同時使
IMCC
的計數器值增長
HIMCC hIMCC );
BOOL WINAPI ImmUnlockIMCC( //
遞減
IMCC
計數器
HIMCC hIMCC );//
若是
IMCC
的計數器值爲零,則返回
FALSE
,不然爲
TRUE.
10
、
HIMCC WINAPI ImmReSizeIMCC( //
從新設置
IMC
的成員的緩衝區大小
HIMCC hIMCC, //IMC
的成員句柄
DWORD dwSize //
新緩衝區大小
);//
若是成功,返回新的
HIMCC
,不然爲
NULL.
DWORD WINAPI ImmGetIMCCSize( //
取
IMC
成員的緩衝區大小
HIMCC hIMCC );//
返回
IMC
成員的緩衝區大小
12
、
DWORD WINAPI ImmGetIMCCLockCount( //
返回
IMC
計數器值
HIMCC hIMCC
);//
成功返回該
IMCC
的計數器值,不然爲
0
BOOL WINAPI ImmGetHotKey( //
取輸入法狀態鍵,該函數供控制面板使用
DWORD dwHotKeyID,
LPUINT lpuModifiers,
LPUINT lpuVKey,
LPHKL lphKL
)
BOOL WINAPI ImmSetHotKey( //
設置輸入法的熱鍵
DWORD dwHotKeyID,
UINT uModifiers,
UINT uVKey,
hKL hKL
)
HWND WINAPI ImmCreateSoftKeyboard( //
產生一個軟鍵盤
UINT uType, //
軟件盤上的鍵碼含義的定義方式
UINT hOwner, //
該輸入法的
UI
窗口
int x, //x
座標
int y //y
座標
);//
成功返回軟鍵盤的窗口句柄
BOOL WINAPI ImmDestroySoftKeyboard( //
銷燬軟鍵盤
HWND hSoftKbdWnd //
軟鍵盤窗口句柄
);//
成功爲
TRUE,
法哦則爲
FALSE.
17
、
BOOL WINAPI ImmShowSoftKeyboard( //
顯示或隱藏軟鍵盤
HWND hSoftKbdWnd, //
軟鍵盤窗口句柄
int nCmdShow //SW_HIDE=
隱藏,
SW_SHOWNOACTIVATE=
顯示
);//
如構成功返回
TRUE.
不然爲
FALSE.
2、
IME
文件中的經常使用結構
1
、
IMEINFOstruct tagIMEInfo { //
輸入法的接口信息
DWORD dwPrivateDataSize;//
用戶設計的數據結構的字節數
DWORD fdwProperty; //
輸入法對鍵盤事件的相應特性
DWORD fdwConversionCaps;//
當前輸入法具備的功能特性
,
若有軟鍵盤、標點、中西文切
換等功能
DWORD fdwSentenceCaps;
DWORD fdwUICaps; //
用戶界面能力:支持軟鍵盤等
DWORD fdwSCSCaps; //
用戶設置編碼串的能力
DWORD fdwSelectCaps; //
輸入法切換時是否使用之前輸入法的模式
} IIMEINFO;
2
、
COMPOSITIONSTR
用於編碼管理
typedef struct tagCOMPOSITIONSTR {
DWORD dwSize; //
當前編碼信息須要的存儲空間
DWORD dwCompReadAttrLen;
//
讀入的編碼屬性長度
DWORD dwCompReadAttrOffset; //
讀入的編碼的位置
DWORD dwCompReadClsLen;
//
讀入的子串長度
DWORD dwCompReadClsOffset; //
讀入的子串的位置
DWORD dwCompReadStrLen;
//
讀入的編碼長度
DWORD dwCompReadStrOffset; //
讀入的編碼的位置
DWORD dwCompAttrLen; //
編碼屬性長度
DWORD dwCompAttrOffset; //
編碼屬性在內存的位置
DWORD dwCompClsLen; //
編碼子串長度
DWORD dwCompClsOffset; //
編碼子串在內存的位置
DWORD dwCompStrLen; //
編碼串長度
DWORD dwCompStrOffset; //
編碼串在內存的位置
DWORD dwCursorPos; //
當前光標位置
DWORD dwDeltaStart; //
被修改編碼的位置
DWORD dwResultReadClsLen; //
讀入結果子串長度
DWORD dwResultReadClsOffset; //
讀入結果子串在內存的位置
DWORD dwResultReadStrLen; //
讀入的編碼長度
DWORD dwResultReadStrOffset;
//
讀入的編碼在內存的位置
DWORD dwResultClsLen; //
結果子串長度
DWORD dwResultClsOffset; //
結果子串在內存的位置
DWORD dwResultStrLen; //
結果串長度
DWORD dwResultStrOffset; //
結果串在內存的位置
DWORD dwPrivateSize; //
用戶自定義數據長度
DWORD dwPrivateOffset; //
用戶自定義數據在內存的位置
} COMPOSITIONSTR;
3
、
CANDIDATEINFO
用於編碼選擇管理
typedef struct tagCANDIDATEINFO {
DWORD dwSize; //
數據所佔內存大小
DWORD dwCount; //
數據個數
DWORD dwOffset[32]; //
各個編碼列表的內存位置
DWORD dwPrivateSize; //
自定義數據尺寸
DWORD dwPrivateOffset; //
緩衝區位置
} CANDIDATEINFO;
4
、
GUIDELINE
typedef struct tagGUIDELINE {
DWORD dwSize;
DWORD dwLevel;
DWORD dwIndex;
DWORD dwStrLen;
DWORD dwStrOffset;
DWORD dwPrivateSize;
DWORD dwPrivateOffset;
} GUIDELINE;
5
、
CANDIDATELIST
編碼選擇列表信息
typedef struct tagCANDIDATELIST {
DWORD dwSize; //
用字節表示的內存大小
DWORD dwStyle; //
列表串的取值方式
DWORD dwCount; //
當前列表個數
DWORD dwSelection; //
當前選擇的列表序號
DWORD dwPageStart; //
在列表窗口中所顯示的列表的起始序號
DWORD dwPageSize; //
一頁顯示的列表個數
DWORD dwOffset[]; //
列表數據存放區地址
} CANDIDATELIST;
6
、
COMPOSITIONFORM
窗口位置、大小信息:
typedef tagCOMPOSITIONFORM {
DWORD dwStyle; //
管理窗口方式
POINT ptCurrentPos; //
給定座標
RECT rcArea;
}COMPOSITIONFORM;
7
、
CANDIDATEFORM
列表窗口信息
typedef tagCANDIDATEFORM {
DWORD dwIndex; //
列表窗口序號
DWORD dwStyle; //
屬性:
POINT ptCurrentPos; //
座標位置
REC rcArea;
} CANDIDATEFORM;
12
、
INPUTCONTEXT IMC
數據存放區
typedef struct tagINPUTCONTEXT {
HWND hWnd; //
使用該
IMC
的窗口
BOOL fOpen; //IME
的打開與關閉狀態
POINT ptStatusWndPos; //
狀態窗口的位置
POINT ptSoftKbdPos; //
軟鍵盤的位置
DWORD fdwConversion; //IME
狀態
(
活動、不活動,全角等)
DWORD fdwSentence; //
編碼方式
union { 代碼編譯完畢