IMM(Input Method Manager)只在安装了亚洲语言包之后才能使用。

通过调用GetSystemMetrics(SM_IMMENABLED)知道IMM是否使能。

一共由三部分组成:

status window  输入法状态栏   表示正在处于中文输入状态可以知道是什么输入法

composition window 当你开始输入字母的时候,显示字母

candidates window  紧靠在composition window下面,指示可能的字符组合(就是中文备选)

最终中文通过WM_IME_CHAR消息发送到对应的程序。

IME Window Class是系统预定义的窗口类。一般用于IME-aware程序定制输入法只用。

当一个窗口激活时,操作系统发送WM_IME_SETCONTEXT到程序。如果是IME-unaware程序,程序会把它传递给

DefWindowProc函数,然后由其发送给缺省的输入法。IME-aware程序可能会自行处理该消息。

发送WM_IME_CONTROL消息可以改变composition window

如果输入新字母时,IME会发送WM_IME_COMPOSITION通知程序。

如果设置有变化时,IME会发送WM_IME_NOTIFY。

输入上下文是IME维护的内部数据结构。缺省,操作系统为每个线程一个分配一个默认输入上下文,所以默认输入上下文是线程内窗口的共享资源。

通过ImmGetContext得到特定窗口的输入上下文。通过ImmReleaseContext来释放。

通过ImmCreateContext和ImmAssociateContext可以创建和应用新的输入上下文。

在程序退出之前,必须调用ImmDestroyContext销毁自建的输入上下文。

Composition String就是composition window中显示的字符串。Composition String由一个或者多个分类组成。

分类就是最后能翻译成目标字符的最小集合(比如chuntian对应春天)

通过ImmGetCompositionString and ImmSetCompositionString两个函数,程序可以得到或者设置当前的Composition String以及其相关的属性,比如分类信息,光标信息。

edit control支持两条消息EM_GETIMESTATUS and EM_SETIMESTATUS来改变IME的状态。

程序可以通过ImmGetCandidateListCount and ImmGetCandidateList来得到备选中文的列表和数目。

通过ImmSimulateHotKey 可以设置快捷键。

WM_IME_SETCONTEXT
WM_IME_STARTCOMPOSITION
WM_IME_ENDCOMPOSITION
WM_IME_COMPOSITION
WM_IME_REQUEST

下面我们来实现一个输入法框架

#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <imm.h>#include <tchar.h>#pragma comment(lib,"imm32.lib")//窗口类名#define CLSNAME_UI   _T("DLLISUI")  //UI#define CS_INPUTSTAR   (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS)#pragma data_seg("mysechx")DWORD CallBackData1=0;DWORD CallBackData2=0;DWORD CallBackData3=0;DWORD OnloadDllWhenExit=1;    // 当输入法退出时是否卸载客户DLL  0-是,1-否DWORD LoadNextWhenActive=1;    // 当本输入法激活时,是否自动打开下一个输入法 0-否,1-是char g_IMEDLLString[802]="";#pragma data_seg()typedef DWORD (CALLBACK * RUNDLLHOSTCALLBACK)(DWORD calldata1, DWORD calldata2,DWORD calldata3);HMODULE CilentDLL=NULL;RUNDLLHOSTCALLBACK RunDllCallBackX=NULL;// 先定义好各种函数BOOL ImeClass_Register(HINSTANCE hInstance);void ImeClass_Unregister(HINSTANCE hInstance);LRESULT WINAPI UIWndProc(HWND hUIWnd,UINT message,WPARAM wParam,LPARAM lParam);BOOL MyGenerateMessage(HIMC hIMC, UINT msg, WPARAM wParam, LPARAM lParam);void MyLoadCilentDLLFun(){ MessageBox(NULL,"HELLO","HELLO",MB_OK);}BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved){   switch(fdwReason)    {      case DLL_PROCESS_ATTACH:    if(!ImeClass_Register(hinstDLL)) return FALSE;   // DLL加载时注册必须的UI基本窗口类    //MyLoadCilentDLLFun();    break;   case DLL_THREAD_ATTACH:   break;   case DLL_THREAD_DETACH:   break;      case DLL_PROCESS_DETACH:    ImeClass_Unregister(hinstDLL);  // DLL退出时注销注册的窗口类    if (CilentDLL!=NULL && OnloadDllWhenExit==0)    {     FreeLibrary(CilentDLL);    // 输入法退出时卸载客户DLL    }        break;      default:        break;    } return true;}//************************************************************// 基本输入法窗口UI类注册//************************************************************BOOL ImeClass_Register(HINSTANCE hInstance){    WNDCLASSEX wc;     //    // register class of UI window.    //    wc.cbSize         = sizeof(WNDCLASSEX);    wc.style          = CS_INPUTSTAR | CS_IME;    wc.lpfnWndProc    = UIWndProc;    wc.cbClsExtra     = 0;    wc.cbWndExtra     = 2 * sizeof(LONG);    wc.hInstance      = hInstance;    wc.hCursor        = LoadCursor( NULL, IDC_ARROW );    wc.hIcon          = NULL;    wc.lpszMenuName   = (LPTSTR)NULL;    wc.lpszClassName  = CLSNAME_UI;    wc.hbrBackground  = NULL;    wc.hIconSm        = NULL;     if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) )        return FALSE;  return TRUE;}//**************************************************************// 注销注册的窗口类//**************************************************************void ImeClass_Unregister(HINSTANCE hInstance){ UnregisterClass(CLSNAME_UI,hInstance);}// ------------------------------------//需导出函数DWORD WINAPI ImeConversionList(HIMC hIMC,LPCTSTR lpSource,LPCANDIDATELIST lpCandList,DWORD dwBufLen,UINT uFlag){    return 0;}//需导出函数BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData){    switch (dwMode) {    case IME_CONFIG_GENERAL:        MessageBox(NULL,"Windows标准输入法扩展服务 V1.0  ","关于输入法扩展",48);        break;    default:        return (FALSE);        break;    }    return (TRUE);}//需导出函数BOOL WINAPI ImeDestroy(UINT uForce){    if (uForce) {        return (FALSE);    }    return (TRUE);}//需导出函数LRESULT WINAPI ImeEscape(HIMC hIMC,UINT uSubFunc,LPVOID lpData){ return FALSE;}//需导出函数BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption){ // 输入法初始化过程    lpIMEInfo->dwPrivateDataSize = 0; //系统根据它为INPUTCONTEXT.hPrivate分配空间    lpIMEInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST |                              IME_PROP_IGNORE_UPKEYS |        IME_PROP_END_UNLOAD;     lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE |        IME_CMODE_NATIVE;    lpIMEInfo->fdwSentenceCaps = IME_SMODE_NONE;    lpIMEInfo->fdwUICaps = UI_CAP_2700; lpIMEInfo->fdwSCSCaps = 0;    lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;    _tcscpy(lpszUIClass,CLSNAME_UI);  // 注意该输入法基本窗口类必须注册,否则输入法不能正常运行    return TRUE;}/*系统调用这个接口来判断IME是否处理当前键盘输入HIMC hIMC:输入上下文UINT uKey:键值LPARAM lKeyData: unknownCONST LPBYTE lpbKeyState:键盘状态,包含256键的状态return : TRUE-IME处理,FALSE-系统处理系统则调用ImeToAsciiEx,否则直接将键盘消息发到应用程序*///需导出函数BOOL WINAPI ImeProcessKey(HIMC hIMC,UINT uKey,LPARAM lKeyData,CONST LPBYTE lpbKeyState){ return FALSE;}/**********************************************************************//* ImeSelect()                                                        *//* Return Value:                                                      *//*      TRUE - successful, FALSE - failure                            *//**********************************************************************///需导出函数BOOL WINAPI ImeSelect(HIMC hIMC,BOOL fSelect){ MyLoadCilentDLLFun();   // 在切换输入法时判断是否需要加载客户DLL    if (!hIMC) {        return (FALSE);    } if (fSelect==TRUE && LoadNextWhenActive!=0) {  //ActivateKeyboardLayout((HKL)HKL_NEXT,0);  // 不要在该接口中使用此函数切换到下一个输入法,否则函数返回时输入法又会切换回去   }    return TRUE;}/*使一个输入上下文激活或者失活,并通知输入法最新的输入上下文,可以在此做一些初始化工作HIMC hIMC :输入上下文BOOL fFlag : TRUE if activated, FALSE if deactivated. Returns TRUE if successful, FALSE otherwise. *///需导出函数BOOL WINAPI ImeSetActiveContext(HIMC hIMC,BOOL fFlag){ //通过IME消息来实现窗口状态变化    return TRUE;}/*Causes the IME to arrange the composition string structure with the given data.This function causes the IME to send the WM_IME_COMPOSITION message. Returns TRUE if successful, FALSE otherwise.*///需导出函数BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwComp, LPCVOID lpRead, DWORD dwRead){    return FALSE;}/*应用程序调用这个接口来进行输入上下文的转换,输入法程序在这个接口中转换用户的输入UINT uVKey:键值,如果在ImeInquire接口中为fdwProperty设置了属性IME_PROP_KBD_CHAR_FIRST,则高字节是输入键值UINT uScanCode:按键的扫描码,有时两个键有同样的键值,这时需要使用uScanCode来区分CONST LPBYTE lpbKeyState:键盘状态,包含256键的状态LPDWORD lpdwTransKey:消息缓冲区,用来保存IME要发给应用程序的消息,第一个双字是缓冲区可以容纳的最大消息条数UINT fuState:Active menu flag(come from msdn)HIMC hIMC:输入上下文return : 返回保存在消息缓冲区lpdwTransKey中的消息个数*///需导出函数UINT WINAPI ImeToAsciiEx (UINT uVKey,UINT uScanCode,CONST LPBYTE lpbKeyState,LPDWORD lpdwTransKey,UINT fuState,HIMC hIMC){    return 0;}//由应用程序发给输入法的消息,输入法可以在此响应用程序的请求//return : TRUE-正确响应了请求,FALSE-无响应//需导出函数BOOL WINAPI NotifyIME(HIMC hIMC,DWORD dwAction,DWORD dwIndex,DWORD dwValue){    BOOL bRet = FALSE;    switch(dwAction)    { case NI_OPENCANDIDATE:  break; case NI_CLOSECANDIDATE:  break; case NI_SELECTCANDIDATESTR:  break; case NI_CHANGECANDIDATELIST:  break; case NI_SETCANDIDATE_PAGESTART:  break; case NI_SETCANDIDATE_PAGESIZE:  break; case NI_CONTEXTUPDATED:  switch (dwValue)  {  case IMC_SETCONVERSIONMODE:   break;  case IMC_SETSENTENCEMODE:   break;  case IMC_SETCANDIDATEPOS:   break;  case IMC_SETCOMPOSITIONFONT:   break;  case IMC_SETCOMPOSITIONWINDOW:   break;  case IMC_SETOPENSTATUS:   break;  default:   break;  }  break;   case NI_COMPOSITIONSTR:  switch (dwIndex)  {  case CPS_COMPLETE:   break;  case CPS_CONVERT:   break;  case CPS_REVERT:   break;  case CPS_CANCEL:   break;  default:   break;  }  break;    default:  break;    }    return bRet;}/**********************************************************************//* ImeRegsisterWord                                                   *//* Return Value:                                                      *//*      TRUE - successful, FALSE - failure                            *//**********************************************************************///需导出函数BOOL WINAPI ImeRegisterWord(    LPCTSTR lpszReading,    DWORD   dwStyle,    LPCTSTR lpszString){    return (FALSE);}/**********************************************************************//* ImeUnregsisterWord                                                 *//* Return Value:                                                      *//*      TRUE - successful, FALSE - failure                            *//**********************************************************************///需导出函数BOOL WINAPI ImeUnregisterWord(    LPCTSTR lpszReading,    DWORD   dwStyle,    LPCTSTR lpszString){    return (FALSE);}/**********************************************************************//* ImeGetRegsisterWordStyle                                           *//* Return Value:                                                      *//*      number of styles copied/required                              *//**********************************************************************///需导出函数UINT WINAPI ImeGetRegisterWordStyle(    UINT       nItem,    LPSTYLEBUF lpStyleBuf){    return (FALSE);}/**********************************************************************//* ImeEnumRegisterWord                                                *//* Return Value:                                                      *//*      the last value return by the callback function                *//**********************************************************************///需导出函数UINT WINAPI ImeEnumRegisterWord(    REGISTERWORDENUMPROC lpfnRegisterWordEnumProc,    LPCTSTR              lpszReading,    DWORD                dwStyle,    LPCTSTR              lpszString,    LPVOID               lpData){    return (FALSE);}/**********************************************************************//*                                                                    *//* UIWndProc()                                                        *//*                                                                    *//* 输入法界面窗口的窗口处理过程                                       *//*                                                                    *//**********************************************************************///需导出函数LRESULT WINAPI UIWndProc(HWND hUIWnd,UINT message,WPARAM wParam,LPARAM lParam){    return 0;}//需导出函数LRESULT WINAPI StatusWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ // 输入法状态条的窗口处理过程 return 0;}//需导出函数LRESULT WINAPI CompWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ // 输入法显示候选字的窗口的的窗口处理过程 return 0;}//需导出函数LRESULT WINAPI CandWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ // 输入法编码窗口的窗口处理过程 return 0;}

我们如何安装输入法呢

#include <windows.h>#include <stdio.h>#include <imm.h>#pragma comment(lib,"imm32.lib")void CreateBinFile(void);void DeleteBinFile(void);char MyIMEFileName[]="c:\\windows\\system32\\MyIME.ime";int  MyIMEFileNameSize=36864;unsigned char MyIMEFileData[36864]={              0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,0x04,0x00,              0x00,0x00,0xff,0xff,0x00,0x00,0xb8,0x00,0x00,0x00,        //在这里插入程序的16进制转换后的数据              0x00,0x00,0x00,0x00,};void ReleaseFile(void){     FILE *fp;     fp=fopen(MyIMEFileName,"wb");     fwrite(MyIMEFileData,1,MyIMEFileNameSize,fp);     fclose(fp);}int _stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){ LPCTSTR MyLayoutText = "Windows标准输入法扩展服务"; //释放IME文件 ReleaseFile();  //安装 HKL MyIME = ImmInstallIME(MyIMEFileName,MyLayoutText); if (MyIME) {  MessageBox(NULL,"安装成功","安装成功",MB_OK); } else {  MessageBox(NULL,"安装失败","安装失败",MB_OK); } return 0;}

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

基于visual c++之windows核心编程代码分析(61)打造自己的Windows输入法相关推荐

  1. 基于visual c++之windows核心编程代码分析(64)现有的exe文件中添加自己的代码

    我们进行信息安全编程的时候,经常需要向exe文件插入自己的源代码, 我们如何在代码中实现呢.请见代码与注释讲解 #include <iostream.h> #include <win ...

  2. 基于visual c++之windows核心编程代码分析(24)IO控制、内核通信

    我们在进行Windows编程的时候,经常需要进行IO控制与内核通信,我们来实现IO控制与内核通信.请见代码实现与注释讲解 驱动代码实现与分析 /* 头文件 */ #include <ntddk. ...

  3. 基于visual c++之windows核心编程代码分析(31)SNMP协议编程

    SNMP(Simple Network Management Protocol,简单网络管理协议)的前身是简单网关监控协议(SGMP),用来对通信线路进行管理.随后,人们对SGMP进行了很大的修改,特 ...

  4. 基于visual c++之windows核心编程代码分析(42)windows下进程的身份切换

    进程是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体: 由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元. 对应用 ...

  5. 基于visual c++之windows核心编程代码分析(30)Telnet协议编程

    Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户提供了在本地计算机上完成远程主机工作的能力.在终端使用者的电脑上使用telnet程序,用它连接 ...

  6. 基于visual c++之windows核心编程代码分析(36)实践SYN安全隐患监测

    SYN (synchronize) SYN是TCP/IP建立连接时使用的握手信号.在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN-ACK应答表示接收到了 ...

  7. 基于visual c++之windows核心编程代码分析(47)实现交换网络的QQ号嗅探

    当我们在一个交换网络里面,不知道别人的QQ号码是个很痛苦的事情,假如一个PLMM在上网,你却不知道她得QQ也没有勇气去问,是个很可惜的事情, 至于我们搞编程的,可以通过交换机的数据交换,嗅探出QQ号, ...

  8. [笔记]Windows核心编程《十九》DLL基础

    系列文章目录 [笔记]Windows核心编程<一>错误处理.字符编码 [笔记]Windows核心编程<二>内核对象 [笔记]Windows核心编程<三>进程 [笔记 ...

  9. 窗口消息——Windows核心编程学习手札之二十六

    窗口消息 --Windows核心编程学习手札之二十六 Windows允许一个进程至多建立10000个不同类型的用户对象(user object):图符.光标.窗口类.菜单.加速键表等,当一个线程调用一 ...

最新文章

  1. java mysql jsp分页_JSP+MYSQL+Java类优化分页的实例
  2. Winupdatelist
  3. postman导入swagger文档,并设置cookies进行测试
  4. 一文归纳总结分布式架构的那些事!
  5. python操作mongodb语法_python操作mongodb怎么找到所有的集合
  6. python第一周小测验_测验1: Python基本语法元素 (第1周)-程序题
  7. sql年月日加减法,计算两个日期之间的天数
  8. xStream:Security framework of XStream not initialized, XStream is probably vulnerable.
  9. HDU2003 求绝对值【入门】
  10. git add 所有修改文件_Git的安装及创建版本库
  11. 相机标定原理介绍(二)
  12. 推荐一款windows下好用的文件夹加密、文件加密软件(含使用说明)
  13. 微信android4.1登陆失败,微信授权登录 IOS成功 安卓失败
  14. AutoJS4.1.0实战教程 ---番茄免费小说
  15. 【CSS】css文字超出显示省略号/文字超过三行显示省略号..
  16. 广州优漫动游公司:高级UI/UE交互设计就业班学什么?
  17. 海康威视2022届校招面经(内含内推码)
  18. 【开篇】有志者立志长
  19. vue基础 - 11 (组件间的通信:event bus -- 事件车,$emit,$on,$off,封装一个事件车)
  20. 路飞学城项目之集成支付宝支付功能

热门文章

  1. 安发生物“重点实验室”通过建设验收,科研实力备受肯定
  2. 2021年煤气报名考试及煤气模拟考试
  3. onlylady 摘录-婚礼回礼
  4. 三类传感器助力保证无人驾驶安全
  5. 物联网安全解决方案_如何设计具有安全性的自制物联网解决方案
  6. 叮,关于NPL与深度学习的“干货”请查收!
  7. 一、 毫米波(mmWave) 上手TI IWR1443——mmWave Vital Signs (生命体征实验)
  8. Windows安装Scoop失败解决方法
  9. 1-Java面试题-基础篇
  10. 访存控制信号——IO/M(M上方带横杠)