freepy自由输入法是由李振春老师产品,在此对李振春老师表示感谢!~~~

项目如图:

输入法与系统的关系如图:

  系统的键盘事件有windows的user.exe软件接收后,user.exe在将键盘事件传导输入法管理器(Input Method Manager,简称IMM)中,管理器 再将键盘事件传到输入法中,输入法根据用户编码字典,翻译键盘事件为对应的汉字(或汉字串),然后再反传到user.exe中,user.exe再将翻译后的键盘事件传给当前正运行的应用程序,从而完成汉字的输入。

你是否了解IME?不了解我们就来简略了解一下吧!~

IME是输入法编辑器!~

IME必须提供两个部件:IME转换接口和IME用户接口。

IME用户界面包括IME窗口、用户界面(UI)窗口以及UI窗口的部件。

缺省输入上下文情况下系统给每个线程一个输入上下文,该输入上下文被线程的所有无IME支持窗口共享。

应用程序的一个窗口可以使用窗口句柄与输入上下文交互以维护任何IME状态,包括中间写作字符串。

当应用程序或者系统创建新的输入上下文时,系统准备新的输入上下文,新的输入上下文已经包括IMCC,这个IMC的部件由hCompStr、hCandInfo、hGuideLine、hPrivate和hMsgBuf组成。

IME需要生成IME消息。当IME开始转换时,IME必须生成WM_IME_STARTCOMPOSITION消息,如果IME改变了写作字符串,IME必须生成WM_IME_COMPOSITION消息,IME引发的事件导致生成消息给与输入上下文进行交互的窗口。

IME与设备驱动程序一样是动态链接库(DLL),输入法管理器(IMM)应该处理所有安装的IME。因为IME在运行时是可以改变的,不需要重新启动系统,IMM有一个结构用于维护每一个IME的所有入口点。

IMM(Input Method Manager)只在安装了亚洲语言包之后才能使用,可以通过调用GetSystemMetrics(SM_IMMENABLED)知道IMM是否使能。

下面是可以在UI窗口中调用的IMM消息、常量、函数:

IME消息以下列出IME中用到的消息。
WM_IME_CHAR(IME得到了转换结果中的一个字符)
WM_IME_COMPOSITION(IME根据用户击键的情况更改了按键组合状态)
WM_IME_COMPOSITIONFULL(IME检测到按键组合窗口的区域无法继续扩展)
WM_IME_CONTROL(由应用程序直接向IME发出控制请求)
WM_IME_ENDCOMPOSITION(IME完成了对用户击键情况的组合)
WM_IME_KEYDOWN(检测到“键盘上的某键被按下”的动作,同时在消息队列中保留该消息)
WM_IME_KEYUP(检测到“键盘上的某键已弹起”的动作,同时在消息队列中保留该消息)
WM_IME_NOTIFY(IME窗口发生了改变)
WM_IME_REQUEST(通知:IME需要应用程序提供命令和请求信息)
WM_IME_SELECT(操作系统将改变当前IME)
WM_IME_SETCONTEXT(输入焦点转移到了某个窗口上)
WM_IME_STARTCOMPOSITION(IME准备生成转换结果)
IME函数本节列出了所有IME函数。
函数说明
EnumInputContext由应用程序定义的,提供给ImmEnumInputContext函数用来处理输入环境的一个回调函数。
EnumRegisterWordProc由应用程序定义的,结合ImmEnumRegisterWord函数一起使用的一个回调函数。
ImmAssociateContext建立指定输入环境与窗口之间的关联。
ImmAssociateContextEx更改指定输入环境与窗口(或其子窗口)之间的关联。
ImmConfigureIME显示指定的输入现场标识符的配置对话框。
ImmCreateContext创建一个新的输入环境,并为它分配内存和初始化它。
ImmDestroyContext销毁输入环境并释放和它关联的内存。
ImmDisableIME关闭一个线程或一个进程中所有线程的IME功能。
ImmDisableTextFrameService关闭指定线程的文本服务框架(TSF)功能--虽然这里把它列了出来,但建议程序员最好不要使用这个函数。
ImmEnumInputContext获取指定线程的输入环境。
ImmEnumRegisterWord列举跟指定读入串、样式和注册串相匹配的注册串。
ImmEscape对那些不能通过IME API函数来访问的特殊输入法程序提供兼容性支持的一个函数。
ImmGetCandidateList获取一个候选列表。
ImmGetCandidateListCount获取候选列表的大小。
ImmGetCandidateWindow获取有关候选列表窗口的信息。
ImmGetCompositionFont获取有关当前用来显示按键组合窗口中的字符的逻辑字体的信息。
ImmGetCompositionString获取有关组合字符串的信息。
ImmGetCompositionWindow获取有关按键组合窗口的信息。
ImmGetContext获取与指定窗口相关联的输入环境。
ImmGetConversionList在不生成任何跟IME有关的消息的情况下,获取输入按键字符组合或输出文字的转换结果列表。
ImmGetConversionStatus获取当前转换状态。
ImmGetDefaultIMEWnd获取缺省IME类窗口的句柄。
ImmGetDescription复制IME的说明信息到指定的缓冲区中。
ImmGetGuideLine获取出错信息。
ImmGetIMEFileName获取跟指定输入现场相关联的IME文件名。
ImmGetImeMenuItems获取注册在指定输入环境的IME菜单上的菜单项。
ImmGetOpenStatus检测IME是否打开。
ImmGetProperty获取跟指定输入现场相关联的IME的属性和功能。
ImmGetRegisterWordStyle获取跟指定输入现场相关联的IME所支持的样式列表。
ImmGetStatusWindowPos获取状态窗口的位置。
ImmGetVirtualKey获取跟IME处理的键盘输入消息相关联的初始虚拟键值。
ImmInstallIME安装一个IME。
ImmIsIME检测指定的输入现场是否有和它相关的IME。
ImmIsUIMessage检查IME窗口消息并发送那些消息到特定的窗口。
ImmNotifyIME通知IME有关输入环境状态已改变的消息。
ImmRegisterWord注册一个输出文字到跟指定输入现场相关联的IME的字典中去。
ImmReleaseContext销毁输入环境并解除对跟它相关联的内存的锁定。
ImmSetCandidateWindow设置有关候选列表窗口的信息。
ImmSetCompositionFont设置用来显示按键组合窗口中的字符的逻辑字体。
ImmSetCompositionString设置按键组合字符串的字符内容、属性和子串信息。
ImmSetCompositionWindow设置按键组合窗口的位置。
ImmSetConversionStatus设置当前转换状态。
ImmSetOpenStatus打开或关闭IME功能。
ImmSetStatusWindowPos设置状态窗口的位置。
ImmSimulateHotKey在指定的窗口中模拟一个特定的IME热键动作,以触发该窗口相应的响应动作。
ImmUnregisterWord从跟指定输入环境相关联的IME的字典中注销一个输出文字。IME命令以下列出IME中用到的命令(控制消息)。
IMC_CLOSESTATUSWINDOW(隐藏状态窗口)
IMC_GETCANDIDATEPOS(获取候选窗口的位置)
IMC_GETCOMPOSITIONFONT(获取用来显示按键组合窗口中的文本的逻辑字体)
IMC_GETCOMPOSITIONWINDOW(获取按键组合窗口的位置)
IMC_GETSTATUSWINDOWPOS(获取状态窗口的位置)
IMC_OPENSTATUSWINDOW(显示状态窗口)
IMC_SETCANDIDATEPOS(设置候选窗口的位置)
IMC_SETCOMPOSITIONFONT(设置用来显示按键组合窗口中的文本的逻辑字体)
IMC_SETCOMPOSITIONWINDOW(设置按键组合窗口的样式)
IMC_SETSTATUSWINDOWPOS(设置状态窗口的位置)
IMN_CHANGECANDIDATE(IME通知应用程序:候选窗口中的内容将改变)
IMN_CLOSECANDIDATE(IME通知应用程序:候选窗口将关闭)
IMN_CLOSESTATUSWINDOW(IME通知应用程序:状态窗口将关闭)
IMN_GUIDELINE(IME通知应用程序:将显示一条出错或其他信息)
IMN_OPENCANDIDATE(IME通知应用程序:将打开候选窗口)
IMN_OPENSTATUSWINDOW(IME通知应用程序:将创建状态窗口)
IMN_SETCANDIDATEPOS(IME通知应用程序:已结束候选处理同时将移动候选窗口)
IMN_SETCOMPOSITIONFONT(IME通知应用程序:输入内容的字体已更改)
IMN_SETCOMPOSITIONWINDOW(IME通知应用程序:按键组合窗口的样式或位置已更改)
IMN_SETCONVERSIONMODE(IME通知应用程序:输入内容的转换模式已更改)
IMN_SETOPENSTATUS(IME通知应用程序:输入内容的状态已更改)
IMN_SETSENTENCEMODE(IME通知应用程序:输入内容的语句模式已更改)
IMN_SETSTATUSWINDOWPOS(IME通知应用程序:输入内容中的状态窗口的位置已更改)
IMR_CANDIDATEWINDOW(通知:选定的IME需要应用程序提供有关候选窗口的信息)
IMR_COMPOSITIONFONT(通知:选定的IME需要应用程序提供有关用在按键组合窗口中的字体的信息)
IMR_COMPOSITIONWINDOW(通知:选定的IME需要应用程序提供有关按键组合窗口的信息)
IMR_CONFIRMRECONVERTSTRING(通知:IME需要应用程序更改RECONVERTSTRING结构)
IMR_DOCUMENTFEED(通知:选定的IME需要从应用程序那里取得已转换的字符串)
IMR_QUERYCHARPOSITION(通知:选定的IME需要应用程序提供有关组合字符串中某个字符的位置信息)
IMR_RECONVERTSTRING(通知:选定的IME需要应用程序提供一个用于自动更正的字符串)
IME编程中需要用到的数据结构这里列了所有在使用输入法编辑器函数和消息时需要用到的数据结构。CANDIDATEFORM(描述候选窗口的位置信息)CANDIDATELIST(描述有关候选列表的信息)COMPOSITIONFORM(描述按键组合窗口的样式和位置信息)IMECHARPOSITION(描述按键组合窗口中的字符的位置信息)IMEMENUITEMINFO(描述IME菜单项的信息)RECONVERTSTRING(定义用于IME自动更正功能的字符串)REGISTERWORD(描述一个要注册的读入信息或文字内容)STYLEBUF(描述样式的标识符和名称)
IME常量这里列出了所有在使用输入法编辑器函数和消息时需要用到的常量。• IME转换模式常量• IME按键组合字符串常量• IME热键标识常量• IME句型模式常量• IMMEscape函数常量

一般汉字输入法都由三个窗口组成:

状态窗口(Status Windows)-显示当前的输入法状态(中文还是英文等站环信息);

编码输入窗口(Composition Windows)-显示当前击键情况;

汉字选择窗口(Candidates Windows)-列出当前编码的全部汉字(串),供用户选择或查询。

上述三个窗口由基本的用户接口(User Interface )函数管理着。

用Dumpbin.exe打开微软提供的拼音输入法(WINDOWS\SYSTEM\WINPY.IME)看看它有什么组成。

19 number of functions //共有19个函数
19 number of names// 对应19个名称 
ordinal hint RVA name
1 0 0000A010 CandWndProc//"选择汉字窗口"注册函数
2 1 0000E750 CompWndProc//"输入编码窗口"注册函数
3 2 0000FB50 ImeConfigure//配置当前ime参数函数 
4 3 0000FEC0 ImeConversionList//将字符或字符串转换成目标字符
5 4 0000FFA0 ImeDestroy//退出当前使用的IME
6 5 000030D0 ImeEnumRegisterWord
7 6 0000FFB0 ImeEscape //应用软件访问输入法的接口函数.
8 7 00003080 ImeGetRegisterWordStyle
9 8 0000E9A0 ImeInquire//启动并初始化当前IME输入法
10 9 0000A800 ImeProcessKey//IME输入键盘事件管理函数
11 A 00002C20 ImeRegisterWord //向输入法字典注册字符串
12 B 000109A0 ImeSelect //启动当前IME输入法
13 C 000109E0 ImeSetActiveContext //设置当前的输入处于活动状态.
14 D 0000C850 ImeSetCompositionString 由应用程序设置输入法编码
15 E 0000AEE0 ImeToAsciiEx//将输入的键盘事件转换为汉字编码事件
16 F 00002F40 ImeUnregisterWord //删除被注册的字符串.
17 10 0000CA90 NotifyIME//IME事件管理函数
18 11 00005160 StatusWndProc//状态窗口注册函数
19 12 00002350 UIWndProc//用户界面接口函数

上述可以看出,IME程序共有19个出口函数组成,每一个函数都有特定的格式,它们担负着与windows 系统传递信息的作用,这些函数是供Windows系统调用的。

下面我们将介绍上述各个函数的功能及接口格式。

1. BOOL ImeInquire( //初始化IME
LPIMEINFO lpIMEInfo, //用于初始化该输入法的结构地址
LPTSTR lpszWndClass, //当前输入法的名称
LPCTSTR或者dword lpszData //系统信息,9X系列值为0,NT/2000下有实际值
)
如果该函数初始化成功,返回TURE,否则为FALSE
用户应该搞清楚IMEINFO结构,特关系着你设计的输入法是否成功.有关该结构请看"结构"一章.
2.DWORD IMEConversionList( // 将某字符或字符串转换成目标字符串
HIMC hIMC, // 与当前输入法相关的应用程序句柄
LPCTSTRlpSrc, // 要转换的字符串 (也可能是结果串,可由uFlag指定)
LPCANDIDATELIST lpDst, /// 转换后的字符串(也可能是源串,可由uFlag指定)
DWORD dwBufLen, //转换后有几个字符
UINT uFlag //指定结果的存放位置
)
如果成功,返回转换后的字符串长度
3.BOOL ImeConfigure( //用户设置输入法接口
HKL hKL, //当前输入法句柄
HWND hWnd, //配置窗口的父窗口
DWORD dwMode, //配置什么
LPVOID lpData //用户设置的数据
)
该函数的功能是提供给输入法使用者一个可以更改某些隐含设置的能力.
如果你用过别人的输入法,其中的"配置输入法..."功能既是也!
对于一个初写输入法的人,可以不予理它.
4.BOOL ImeDestroy( //关闭当前输入法
UINT uReserved //无用 (0)
)
成功返回TURE,否则为FALSE
5.LRESULT ImeEscape( //用户软件访问输入法内部信息的接口
HIMC hIMC, //当前的应用程序句柄
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)
//=IME_ESC_PRIVATE_HOTKEY(w95下不可用)
LPVOID lpData //当前功能所需的数据
)
如果失败,返回0,否则有个功能决定
有时,人们可以用此函数怀区输入法的名称、帮助文件名称等。当然,我们可以不提供这些功能。6、BOOL ImeSetActiveContext( //激活或搁置当前的输入法
HIMC hIMC, //当前用户程序句柄
BOOL fFlag //激活或搁置:=TRUE 激活 =FALSE 搁置
)
成功返回TRUE,否则为FALSE
7、BOOL ImeProcessKey( //处理应用程序传入的所有击键事件,监测是否是当前输入法所需的
HIMC hIMC, //应用程序句柄
UINT uVirKey, //需处理的虚键
DWORD lParam, //击键消息参数
CONST LPBYTE lpbKeyState //当前键盘状态(256字节)
)
如果此键是该输入法需要的,则返回TRUE,否则为FALSE
只有返回true的击键,IME才去处理
8、BOOL NotifyIME( //输入法选择窗口状态管理函数:
HIMC hIMC, //当前的应用程序句柄
DWORD dwAction, //状态值
DWORD dwIndex, //与状态值有关的序号
DWORD dwValue //与状态值有关的值
)
状态值说明:
=NI_OPENCANDIDATE 打开编码选择窗口
=NI_CLOSECANDIDATE 关闭当前的编码选择窗
=NI_SELECTCANDIDATESTR 选摘编码
此时:dwIndex 被选择的编码列表序号.
dwValue 被选中的编码在当前的编码列表中的序号
=NI_CHANGECANDIDATELIST 改变当前的编码列表(按pageup等键操作)
此时:dwIndex 被选择的编码列表序号.
dwValue 不用
=NI_SETCANDIDATE_PAGESTART 设置编码开始页号
此时: dwIndex 被改变的编码列表序号
dwValue 新页的开始序号.
=NI_SETCANDIDATE_PAGESIZE 改变编码列表页的大小
此时:dwIndex 当前编码页序号
dwValue 新的页大小
=NI_CONTEXTUPDATED 更新应用程序的信息的输入法的信息:移动位置,设置模式,设置编码窗口,字体。
此时:dwIndex 只用于 dwValue=IMC_SETCONVERSIONMODE, IMC_SETSENTENCEMODE
dwValue 可取由 WM_IME_CONTROL 发送的下列值:
IMC_SETCANDIDATEPOS
IMC_SETCOMPOSITIONFONT
IMC_SETCOMPOSITIONWINDOW
IMC_SETCONVERSIONMODE
IMC_SETSENTENCEMODE
IMC_SETOPENSTATUS
=NI_COMPOSITIONSTR 改变编码窗口中的编码
此时:dwIndex 取下列值:CPS_COMPLETE 完成编码转换
CPS_CONVERT 转换编码
CPS_REVERT 取消当前的编码
CPS_CANCEL 清除编码,并关闭编码窗
dwValue 不用
此函数成功,返回TRUE,否则为FALSE
9、BOOL ImeSelect( //初始化输入法
HIMC hIMC, //当前应用程序句柄
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)给系统,
HIMC hIMC, //当前的应用程序句柄
DWORD dwIndex, //设置此函数功能
//=SCS_SETSTR
//=SCS_CHANGEATTR
//=SCS_CHANGECLAUSE
//= SCS_QUERYRECONVERTSTRING
//=SCS_RECONVERTSTRING
//=SCS_SETRECONVERTSTRING LPCVOID lpComp, //编码数据区
DWORD dwCompLen, //编码数据区长度
LPCVOID lpRead, //读入的编码数据
DWORD dwReadLen //读入的编码数据长度
)
11、UINT ImeToAsciiEx( //转换编码称汉字(串)
UINT uVirKey, //虚键
UINT uScanCode, //扫描码
CONST LPBYTE lpbKeyState, //用户定义的键盘状态
LPDWORD lpdwTransBuf, //转换后的数据存放区
UINT fuState, //活动菜单标志
HIMC hIMC //当前的应用程序句柄
)
返回:返回值表示有几个消息,可理解为:本编码对应的汉字串有几个汉字组成(当然,这并不相等)。
12、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
)
……
下面进入到freepy里Freepy的执行顺序是: 1.   注册UI窗口类(DllMain:   DLL_PROCESS_ATTACH) 2.   初始化当前输入法(回凋函数ImeInquire) 3.   启动当前输入法(回凋函数ImeSelect) 4.   UIWndProc 5.   CompWndProc 6.   StatusWndProc ... X.   结束,释放资源(DllMain:   DLL_PROCESS_DETACH) 
消息循环注册了四个窗口类 根据wc.lpszClassName注册不同窗口注: 可以参考 res/BMP文件的命名CandWndProc  //"选择汉字窗口"注册函数  撰写窗口, 当你开始输入字母的时候,显示字母CreateCompWindow    "输入编码窗口"注册函数void LoadTable() 加载字体库
字体显示  查询相关位图,通过LoadBitmap 得到位图加载显示

注册测试代码:

void main()
{HKEY hKey,hChildKey;DWORD dwIndex;DWORD dwName,dwMaxName = 0;TCHAR szNameArr[MAX_SUBKEY][MAX_SIZE],szName[MAX_SIZE];DWORD dwLen;TCHAR szLayoutText[MAX_SIZE];DWORD dwData;FILETIME ft;LONG lRet;TCHAR szRegName[MAX_SIZE];DWORD dwDisposition;DWORD dwConversionSet;WORD wCount = 0;int i;OSVERSIONINFO osVerInfo;dwIndex = 0;dwLen = MAX_SIZE;dwData = MAX_SIZE * sizeof(TCHAR);dwConversionSet = CONVERSION_SET;if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software"),0,KEY_READ,&hKey) != ERROR_SUCCESS ){_ftprintf(stderr,_T("Software open error\n"));exit(1);}if( RegCreateKeyEx( hKey,_T("freepy"),0,NULL,REG_OPTION_NON_VOLATILE ,KEY_ALL_ACCESS ,NULL,&hChildKey,&dwDisposition ) != ERROR_SUCCESS) {RegCloseKey(hKey);_ftprintf(stderr,_T("freepy create error\n"));exit(1);}RegSetValueEx(hChildKey,_T("ConversionSet"),0,REG_DWORD,(LPBYTE)&dwConversionSet,sizeof(DWORD));RegCloseKey(hChildKey);RegCloseKey(hKey);if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("System\\CurrentControlSet\\Control\\Keyboard Layouts"),0,KEY_READ,&hKey) != ERROR_SUCCESS ){_ftprintf(stderr,_T("Keyboard Layouts open error\n"));exit(1);}RegQueryInfoKey (hKey,NULL,   NULL,NULL,&dwIndex,NULL,NULL,NULL,  NULL,NULL,NULL, NULL);while( (int)dwIndex >= 0 ) {dwLen = MAX_SIZE;if((lRet = RegEnumKeyEx(hKey,dwIndex,szName,&dwLen,NULL,NULL,NULL,&ft)) == ERROR_SUCCESS || lRet == ERROR_MORE_DATA ) {_tcscpy(szNameArr[wCount++],szName);}dwIndex--;}for(i=0;i<wCount;i++) {if ( RegOpenKeyEx(hKey,szNameArr[i],0,KEY_ALL_ACCESS ,&hChildKey) == ERROR_SUCCESS ){if( RegQueryValueEx( hChildKey,_T("Layout Text"),NULL,NULL,(LPBYTE)szLayoutText,&dwData) == ERROR_SUCCESS ){if(!_tcsicmp(szLayoutText,LAYOUTTEXT)) {goto my_next;}_stscanf(szNameArr[i],_T("%lx"),&dwName);if( dwMaxName < dwName ) dwMaxName = dwName;}RegCloseKey(hChildKey);}}_stprintf(szRegName,"%lx",dwMaxName + 0x10000);CharUpper(szRegName);if( RegCreateKeyEx( hKey,szRegName,0,NULL,REG_OPTION_NON_VOLATILE ,KEY_ALL_ACCESS ,NULL,&hChildKey,&dwDisposition ) != ERROR_SUCCESS) {RegCloseKey(hKey);_ftprintf(stderr,_T("%s create error\n"),szRegName);exit(1);}my_next:RegSetValueEx(hChildKey,_T("IME File"),0,REG_SZ,(LPBYTE)IMEFILE,_tcslen(IMEFILE)*sizeof(TCHAR));osVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);if(GetVersionEx(&osVerInfo)) {RegSetValueEx(hChildKey,_T("Layout File"),0,REG_SZ,(osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ?((LPBYTE)LAYOUTFILENT):((LPBYTE)LAYOUTFILE),_tcslen(LAYOUTFILENT)*sizeof(TCHAR));}else {_ftprintf(stdout,_T("get version error\n"));RegSetValueEx(hChildKey,_T("Layout File"),0,REG_SZ,(LPBYTE)LAYOUTFILE,_tcslen(LAYOUTFILE)*sizeof(TCHAR));}RegSetValueEx(hChildKey,_T("Layout Text"),0,REG_SZ,(LPBYTE)LAYOUTTEXT,_tcslen(LAYOUTTEXT)*sizeof(TCHAR));RegCloseKey(hChildKey);RegCloseKey(hKey);_ftprintf(stdout,_T("ok\n"));return;
}

最后介绍一下它的调式技巧!~

打开freepy3.1工程,打开vc主菜单的Projectttings的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。设置断点,然后按F5,进行调试,这时候打开任务栏右下脚输入法里的自由拼音输入法就可以了。

学习的目标是成熟!~~~~

开源项目之freepy自由输入法相关推荐

  1. Github优秀Android开源项目,值得引用与学习(图文结合~~~)

    刚进来的时候需要加载很多图片和gif图片, 所以想看图片效果需要耐心等待一下. JKeyboardPanelSwitch Android键盘面板冲突 布局闪动处理方案 点我跳转 给大家提供一个底部导航 ...

  2. Github优秀Android开源项目,值得引用与学习(注意!里面有巨图! )

    内容添加(--根据trending(today)/java从上往下添加的,根据时间查看,都是github的项目,以及大佬们的点赞的GitHub项目 ) 刚进来的时候需要加载很多图片和gif图片, 所以 ...

  3. 2013年度中国优秀开源项目

    2013年度中国优秀开源项目 当前63票 ACL 一个通用网络通信库,为C/ C++程序员提供高效.稳定.可靠.功能强大的开发通讯与服务器框架,以及各种常见应用协议的客户端库. 当前70票 Ansj中 ...

  4. 开源项目推荐:本人收集的有关Qt的GitHub/Gitee开源项目(★精品收藏★)

    尊重作者,支持原创,如需转载,请附上原地址:开源项目推荐:Qt有关的GitHub/Gitee开源项目(★精品收藏★)_$firecat全宏的代码足迹$-CSDN博客_qt开源项目https://lib ...

  5. 分享Silverlight 3D 房屋设计 和 游戏 开源项目

    2011-05-03 06:53 by jv9, 2849 阅读, 6 评论, 收藏, 编辑 Silverlight 5 Beta版本中最引人注目的特性是3D功能,Silverlight 5与XNA ...

  6. 分享Silverlight 3D开源项目和Silverlight/WPF/Windows Phone一周学习导读(4月25日-4月29日)...

    Silverlight 5 Beta版本中最引人注目的特性是3D功能,Silverlight 5与XNA Framework的结合,使Silverlight完美支持3D效果. 在微软MIX11大会后, ...

  7. windows下nodejs express安装及入门网站,视频资料,开源项目介绍

    windows下nodejs express安装及入门网站,视频资料,开源项目介绍,pm2,supervisor,npm,Pomelo,Grunt安装使用注意事项等总结 第一步:下载安装文件 下载地址 ...

  8. 人工智能和机器学习领域有哪些有趣的开源项目

    人工智能和机器学习领域有哪些有趣的开源项目? 投递人 itwriter 发布于 2014-12-02 11:21 评论(0) 有20人阅读  原文链接  [收藏]  « 本文简要介绍了 10 款   ...

  9. 我是如何通过开源项目月入 10 万的?

    加个"星标",天天中午 12:15,一起学算法 作者 | GitHubDaily 来源 | GitHubDaily 前言 如果你是一名前端工程师,那么你一定对 fullPage.j ...

最新文章

  1. linux服务 Systemd 简介
  2. python用途与前景-Python的发展前景及干货!!
  3. 从上千篇论文脱颖而出,支付宝论文凭什么获得WWW2020评委认可?
  4. 【jzoj3734,Usaco2014Open银组】双导航(gpsdual)
  5. Java基础入门笔记-数组链表
  6. 信息学奥赛一本通 1233:接水问题 | 1950:【10NOIP普及组】接水问题 | OpenJudge NOI 1.9 15 | 洛谷 P1190 [NOIP2010 普及组] 接水问题
  7. python接口自动化(四十)- logger 日志 - 下(超详解)
  8. ajax的总结和使用
  9. linux编程排序,Linux下简单的c编程——选择法排序
  10. 【Dairy】2016.10.30 BirthdayParty
  11. 4.7 Observer(观察者)
  12. python解析mht文件_php解析mht文件转换成html
  13. 大数据预测房价湖北暂未实施
  14. 歌评 Mondstadt Starlit 星光下的蒙德-陈致逸
  15. 如何在TIA 博途 WinCC中组态WinCC Runtime Advanced 和 S7 控制器的PROFINET通信连接?
  16. 2022年初级审计师考试综合试题及答案
  17. (读书笔记) 暗时间 (2016.12.17更)
  18. 火狐同步safari书签_如何将Safari浏览器的Chrome,Firefox和Internet Explorer书签同步
  19. 2021年三季度中国通用设备行业A股上市企业营收排行榜:22家企业自2017年起第三季度的净利润逐年递增(附热榜TOP100详单)
  20. sap发出商品差异差异分摊_什么是差异隐私?

热门文章

  1. Android 4.0.4-在build.prop中添加属性
  2. 记录更换固态硬盘免重装系统和环境的操作
  3. GTSAM 学习(一)
  4. 历代诗词咏宁夏注释1----常星景: 六盘
  5. android 老人机模式,如何将智能手机切换成老人机模式
  6. 计算机应用word单元测试2,计算机应用基础测试题2
  7. 力扣(1053.115)补9.13
  8. c++中如何将数组赋值给vector
  9. 线性代数和微积分 1.1微分方程概述
  10. 【Niagara Vykon N4】物联网学习 02 照明控制