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

在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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值