(转)Windows应用程序中动态的控制输入法
luyued 发布于 2011-02-20 11:56 浏览 N 次
在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
本文将对如何在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
上一篇:LPT激光溶脂的优势有哪些 下一篇:使用usb转并口线虚拟LTP1端口打印设置
相关资讯
- 06-21· 爱可视605WIFI暑促!购机还送
- 06-21· 疯狂降价1200元爱可视404
- 06-11· Ellen呼吁粉丝协力阻止捕杀
- 06-11· 【引用】『八卦』未来英
- 06-10· 升级Android 2.2!爱可视101评
- 06-10· 爱可视环球首发5款Androi
- 06-09· 台湾母子3人因贫病交迫中
- 06-09· Genetically modified tobacco co
- 06-09· 英国《独立报》:中国女演
- 06-09· Rascal Flatts - Summer Nights (
最新资讯
- 06-09· 收音机厂商(22)
- 06-08· 问板终极贴【2009年6月20日
- 06-08· 爱可视平板电脑新品 让你
- 06-08· 升级Android2.2!爱可视101平板
- 06-08· 法国爱可视推出限量版上
- 06-08· 高清之王爱可视AV530仅售
- 06-08· ARCHOS-605 爱可视--30GB-触摸
- 06-08· [转载]【原创】爱可视10
- 06-07· c++标准库中endl的实现(转
- 06-07· 单指令多数据的程序优化