Windows深输入法编程

本文介绍了一种在Windows应用程序中实现智能输入法自动切换的方法。通过封装Windows API函数,创建了一个C++类,能够动态地控制输入法。文章详细介绍了如何获取已安装的输入法信息,并通过示例代码展示了如何实现输入法的加载和选择。
 
Windows系统中一般都安装了至少三种输入法,在输入数据时常常会切换输入法,虽然Windows系统提供了切换快捷健,但对输入工作还是带来了不少麻烦。如果在应用程序中为用户提供智能输入法自动切换,那么这样的应用程序就显得更加专业、更加具有竞争力。不知你可用过Access,在表数据输入时Access自动切换输入法,如某字段需要输入英文时自动切换到En输入状态,如另一字段需要输入中文自动切换到某中文输入状态。
 
本文将对如何在Windows应用程序中动态的控制输入法的技术进行探讨。在Delphi中许多控件都有控制输入法的属性,用户在设计时只要设置好这个属性就可以了,但在VC中并不直接提供对输入法的控制,要在VC应用中实现这种功能必须调用Windows API。在这里将用一个类将与输入法操作有关的Windows API函数进行封装,通过操作这个类来实现对输入法的控制,这样更适合于面向对象的开发。
 
要想控制输入法,首先要解决的问题是如果获得系统已安装的输入法信息。在Windows平台下,每个安装的输入法都在注册表中注册了相关信息。在“HKEY_CURRENT_USER/keyboard layout/preload”键下就可以找到这些信息,键下由以1为基的递增数字做为值名(暂取名为数字号),其值的内容是一个由八个数字组成的字符串(暂取名为代号,如"e0040804"),其中左4位是设备代码(device identifier),右4位是语言代码(language identifier)。例如上面:左e004指智能ABC,右0804指大陆中文。另外要说明一点的是在Windows98版本中输入法注册信息与上面说明略有不同,它是将已安装的输入法的数字号做为…/Preload下面的子键,而Windows2000将数字号做为…/Preload键下的值。
 
通过读取注册表中的输入法信息,可以列出所有已安装的输入法,但得到的输入法信息只是一些让人难懂的数字串,如何将这些数字串翻译成易懂的文字说明呢?同样,在HKEY_LOCAL_MACHINE:"System/CurrentControlSet/Control/Keyboard Layouts/"键下注册了这些信息,它的子键名为输入法代号(keyboard layout),内容为该输入法的ime文件,名称等信息。到此,我们已经了解了Windows系统控制输入法的原理知识,下面我们开始着手创建一个控制输入法的C++类,主要步骤如下:
  1. 创建一个新类,新类名为:CInputLanguage
  2. 新建一个保存输入法信息的结构。当加载系统已安装的输入法信息时,用一个此结构的链表来保存输入法信息。
  struct IL{
  char ilID[15]; //输入法代号。
  char szName[100];//输入法的说明文字。
  IL* pNext;
  };
  3. 加入一个私有的成员变量
  IL* m_pILHead;
  4. 加入加载输入法列表信息的成员函数
  //此函数只针对Windows2000以上版本
  BOOL CInputLanguage::LoadInputLanguage()
  {
  HKEY hKey,hKey1;
  DWORD cp=16;
  char lp[15];
  CString szID;
  CString szKeyName,szKeyName1;
  szKeyName = "Keyboard Layout//Preload";
  szKeyName1 = "System//CurrentControlSet//Control//Keyboard Layouts//";
  int i=1;
  szID.Format("%d",i);
  DWORD lpT=REG_SZ;
  if(::RegOpenKey(HKEY_CURRENT_USER,szKeyName,&hKey)==ERROR_SUCCESS )
  {
  While( ::RegQueryValueEx(hKey,szID,NULL,&lpT,(LPBYTE)lp,&cp) == ERROR_SUCCESS )
  {
  CString szTempName;
  szTempName = szKeyName1 + (LPCTSTR)(LPTSTR)lp;
  if(RegOpenKey(HKEY_LOCAL_MACHINE,szTempName,&hKey1)==ERROR_SUCCESS )
  {
  char lpD[100];
  DWORD lpS=100; //DataSize
if(RegQueryValueEx(hKey1,"Layouttext",NULL,&lpT,(LPBYTE)lpD,&lpS)
==ERROR_SUCCESS)
  {
  IL* p1,*p2;
  p1 = m_pILHead;
  p2 = new(IL);
  strcpy(p2->ilID,lp);
  strcpy(p2->szName,lpD);
  p2->pNext = NULL;
  if( p1 )
  {
  while( p1->pNext ){ p1 = p1->pNext ; }
  p1->pNext = p2;
  }
  else
  {
  m_pILHead = p2;
  }
  }
  }
  ::RegCloseKey(hKey1);
  i++;
  szID.Format("%d",i);
  }
  }
  ::RegCloseKey(hKey);
  return (m_pILHead != NULL );
  }
5. 加入选择输入法成员函数
  BOOL CInputLanguage::SelectInputLanguage(IL *pIL)
  {
  if( !pIL ) return FALSE;
  HKL hkl;
  hkl=LoadKeyboardLayout(pIL->ilID,KLF_ACTIVATE);//装载输入法
  if(hkl==NULL) return FALSE;
  else{
  ActivateKeyboardLayout(hkl,KLF_SETFORPROCESS);//激活输入法
  }
  return TRUE;
  }
  6. 其它部分
  CInputLanguage::CInputLanguage()
  {
  m_pILHead = NULL;
  LoadInputLanguage();
  }
  CInputLanguage::~CInputLanguage()
  {
  Clear();
  }
  //消除链表内存。
  void CInputLanguage::Clear()
  {
  IL* p1,*p2;
  p1 = m_pILHead;
  while( p1 )
  {
  p2 = p1;
  p1 = p1->pNext;
  delete(p2);
  }
  m_pILHead = NULL;
  }
  //获得输入法信息链表头结点指针。
  IL* CInputLanguage::GetInputLanguageList()
  {
  return m_pILHead;
  }
  使用此类时,只要将其头文件包括到要调用的文件中,调用GetInputLanguageList函数可以得到输入法信息链表的头结点指针,通过遍历此链表得到所有已安装的输入法的信息;通过SelectInputLanguage函数可以自由的控制输入法了
 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值