(转)Windows应用程序中动态的控制输入法

    技术2025-08-31  27

    在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指大陆中文。在MSDN中对所有代码做了详细的说明,如感兴趣请浏览MSDN相关内容。另外要说明一点的是在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以上版本,如要在Windows98版本的代码请与笔者联系。 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, "Layout   text ",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函数可以自由的控制输入法了 

     

    转自: http://topic.csdn.net/t/20040113/10/2659188.html

    最新回复(0)