IME可以设置要打开的中文输入法么?比如我想打开智能ABC,应该怎么写代码呢?请达人指点一下迷津,谢谢

解决方案 »

  1.   

    看完你应很清楚,以前收藏的,呵呵 
    Visual C++编程控制输入法 2003-03-07 
    在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函数可以自由的控制输入法了 
      

  2.   

    看过这篇文章了,就是里面的while循环执行不了
      

  3.   

    我直接用RegQueryValueEx查询注册表中Keyboard Layout中Preload的值,其返回值是2,但其中是有值的啊,怎么回事?代码如下:
    BOOL CRegEditDlg::OnInitDialog()
    {
    CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE); // 设置大图标
    SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码
    HKEY hKey;
    DWORD data;
    DWORD size;
    DWORD type = REG_SZ;
    CString szID;
    szID.Format(_T("%d"),1);
    CString szKeyName = _T("Control Panel"); long iret = RegOpenKeyEx(HKEY_CURRENT_USER,szKeyName,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,&hKey);
    if(iret == 0)
    {
    CString value;
    iret = RegQueryValueEx(hKey,_T("Colors"),0,&type,(BYTE *)&data,&size);
    if(iret == 0)
    {
    value.Format(_T("%d"),data);
    MessageBox(value,_T("Query result is:"),MB_OK);
    RegCloseKey(hKey);
    }
    else
    {
    CString strerr;
    strerr.Format(_T("return%d"),iret);
    MessageBox(strerr,_T("error"),MB_OK);
    } }

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    }
      

  4.   

    那应该怎么写?比如路径是HKEY_CURRENT_USER\Keyboard Layout\Preload,Preload中有一个默认值和3个其它值,要读取这3个其它值应该怎么写RegOpenKeyEx和RegQueryValueEx的参数?