激烈振动

Visit My MSN Space

导航

用代码控制输入法的切换+输入法菜单

不知道多少人会需要这样的东西,也许不多,以至于在网上搜索的时候,很少这样的资料。我因为做模拟操作系统环境的软件,碰到这样的需求,要求显示输入法菜单,并用鼠标选择输入法。其实也不是很难,只是挺偏,一般很少需要做这样的事情。现在完成了,归纳出一个类,代码不长,干脆贴在这里,为有需要的朋友帮点忙,或许会有用。
开始写的时候本来是借用了MFC的一些类,CString, CMenu之类的。但是用的不多,所以为了通用性强些,干脆把那些代码全改成SDK函数了,现在应该可以用在任何一个C++做的Windows项目里面。
一般的用法就是实例化类,然后调用DoMenu函数显示选择菜单就可以了,用鼠标选中后会自动切换到指定的输入法。这个类里面使用了最普通的菜单,所以没法象Windows系统那样在输入法菜单中显示输入法的图标。不过要实现其实也很简单,因为这个输入法类提供了获取输入法图标的函数(GetIcon),自己找一个支持图标的菜单类用上去就可以了。这里顺带推荐一下本人以前写的菜单类,我觉得功能还是比较强的 
当然了,那样代码会长写,就没法在一篇blog里面直接贴出来了,用兴趣的朋友自己完成了,也不是很麻烦的。下面就是完整的代码了,用一个头文件实现的,很短,现在特别喜欢很短的代码

#pragma once

#include "imm.h"

#pragma comment(lib, "imm32")

//////////////////////////////////////////////
// Input method helper class
class ImeHelper
{
private:
 HKL  m_hkls[100];
 int  m_nCount;
public:

 ImeHelper(void)
 {
  m_nCount = ::GetKeyboardLayoutList(100, m_hkls);
 }

 ~ImeHelper(void)
 {
 }

 int GetCount()
 {
  return m_nCount;
 }

 HKL GetHKL(int nIndex)
 {
  if (nIndex<0 || nIndex>m_nCount)
   return NULL;

  return m_hkls[nIndex];
 }

 void ActivateIme(HKL hkl)
 {
  if (hkl != NULL)
   ::ActivateKeyboardLayout(hkl, 0);
 }

 void DoMenu(HWND hwnd, int x, int y)
 {
  HMENU hMenu = CreatePopupMenu();
  int nCmd = ::TrackPopupMenuEx(hMenu, TPM_LEFTBUTTON | TPM_RETURNCMD, x, y, hwnd, NULL);
  
  if (nCmd>=0 && nCmd<m_nCount)
   ActivateIme(GetHKL(nCmd));

  ::DestroyMenu(hMenu);
 }

 CString GetDescription(HKL hkl)
 {
  char szDesc[200];
  memset(szDesc, 0, 200);
  ::ImmGetDescription(hkl, szDesc, 200);
  if (strlen(szDesc)==0)
  {
   //sprintf(szDesc, "0x%x", (UINT)hkl);
   WORD wLang = LOWORD(hkl);
   switch (wLang)
   {
   case 0x0804:
    sprintf(szDesc, "中文");
    break;
   case 0x0409:
    sprintf(szDesc, "英语");
    break;
   default:
    break;
   }
  }
  return szDesc;
 }

 LPCTSTR GetImeFile(HKL hkl)
 {
  static char szFile[256];
  memset(szFile, 0, 256);
  ::ImmGetIMEFileName(hkl, szFile, 255);
  return szFile;
 }

 int CurrentIndex()
 {
  HKL hkl = ::GetKeyboardLayout(::GetCurrentThreadId());
  for (int i=0; i<m_nCount; i++)
  {
   if (hkl == m_hkls[i])
    return i;
  }
  return -1;
 }

 HICON GetIcon(HKL hkl)
 {
  HICON hIcon = NULL;
  LPCTSTR szImeFile = GetImeFile(hkl);
  if (strlen(szImeFile)==0)
  {
   //return a default icon
  }
  else
  {
   HMODULE hModule = ::LoadLibrary(szImeFile);
   if (hModule)
   {
    hIcon = ::ExtractIcon(hModule, szImeFile, 0);
    ::FreeLibrary(hModule);
   }
  }
  return hIcon;
 }

private:
 //Create a popup menu of all input method
 HMENU CreatePopupMenu()
 {
  HMENU hMenu = ::CreatePopupMenu();

  for (int i=0; i<m_nCount; i++)
  {
   ::AppendMenu(hMenu, (CurrentIndex()==i)?MF_CHECKED:0, i, GetDescription(GetHKL(i)));
  }

  return hMenu;
 }

};

posted on 2004-04-14 13:39  vibration  阅读(4767)  评论(4编辑  收藏  举报