用代码控制输入法的切换+输入法菜单
不知道多少人会需要这样的东西,也许不多,以至于在网上搜索的时候,很少这样的资料。我因为做模拟操作系统环境的软件,碰到这样的需求,要求显示输入法菜单,并用鼠标选择输入法。其实也不是很难,只是挺偏,一般很少需要做这样的事情。现在完成了,归纳出一个类,代码不长,干脆贴在这里,为有需要的朋友帮点忙,或许会有用。
开始写的时候本来是借用了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) 编辑 收藏 举报