c++实现输入法窗口自定义的代码
#pragma once
#include <Windows.h>
#include <imm.h>
#include <string>
#pragma comment ( lib , "imm32.lib" )
//字符串临时缓存长度
#ifndef _MAX_BUF_
#define _MAX_BUF_ 256
#endif
/*
功能:取输入法窗口候选字列表,输入法名称及状态
为自己绘制“输入法窗口”创造必要条件。
标题:实现输入法窗口自定义
关键词:IME VC 输入法 输入法窗口
最后修改日期:2010-09-02
Remark:当前环境VS2008+SP1 WinXPSP3。编译选项为Unicode。
http://dev.gameres.com/Program/Control/ime.htm
CGetIme为单实例类
测试:在Irrlicht1.7.1中测试通过。
在标准Win32窗口程序中测试通过。
*/
class CGetIme
{
public:
CGetIme(void)
{
m_hWnd = NULL ;
}
~CGetIme();
//功能:初始化当前类的实例,使之可用。
//Remark:你只能在hWnd的属主(线程)中调用这个函数
//建议在WM_CREATE或WM_IME_SETCONTEXT中调用
void setHWnd(HWND hWnd);
//功能:取候选字列表,和当前输入的候选key
//Remark:建议在WM_IME_NOTIFY的wParam为以下
//IMN_OPENCANDIDATE和IMN_CHANGECANDIDATE事件
//时调用
//strCS=>已经键入的Key,strCL=>候选字列表
void getCandidateList(std::string &strCS,std::string &strCL);
//功能:取输入法名称
std::string getDescription();
//功能:取输入法状态
std::string getConversion();
//Remark:建议在IMN_CLOSECANDIDATE事件时,关掉对“自定义输入法窗口”的绘制。
//Remark:WM_IME_CHAR事件中,你会得到,转换后的字符串,
//不过你是一个wchar_t一个wchar_t的得到,参考下面的代码段
//char bits [2] = { (char) ((wParam & 0xff00)>> 8), (char) (wParam & 0xff) },wchar_t t = bits;
//禁止输入法
void disableIME();
//允许输入法
void enableIME();
protected:
HWND m_hWnd;
HIMC m_hIMC;
std::string m_candidate; //候选字列表
std::string m_description; //输入法名称
std::string m_conversion; //输入法状态
std::string m_compstr; //已经键入的key
};
//=======================================================
#include "StdAfx.h"
#include "GetIme.h"
#include <assert.h>
#include "../T3D3_Irrlicht161/Utils.h"
void CGetIme::setHWnd(HWND hWnd)
{
m_hWnd = hWnd;
//ImmGetContext cannot get input context of other process. ImmGetContext internally
//checks whether the process of the target window is the current process.
//If the check fails, the function returns NULL.
m_hIMC = ::ImmGetContext(m_hWnd);
assert(m_hIMC);
//Below,Hide IME window
HWND hWndIME = ::ImmGetDefaultIMEWnd(hWnd);
if (hWndIME)
::ShowWindow(hWndIME,SW_HIDE);
}
CGetIme::~CGetIme()
{
//Show IME window
HWND hWndIME = ::ImmGetDefaultIMEWnd(m_hWnd);
if (hWndIME)
::ShowWindow(hWndIME,SW_SHOW);
ImmReleaseContext(m_hWnd, m_hIMC);
}
void CGetIme::getCandidateList(std::string &strCS,std::string &strCL)
{
std::string sR("");
wchar_t buf[32];
char *p;
int nR;
DWORD dwSize;
LPCANDIDATELIST lp;
m_candidate = "";
m_compstr = "";
HKL hKL = ::GetKeyboardLayout(0);//获得键盘布局
if (hKL==0)
{
OutputDebugString(L"hKL==0/n");
return ;
}
if( m_hIMC == NULL)
{
OutputDebugString(L"hIMC ==0/n");
return ;
}
ZeroMemory(buf,sizeof(buf));
ImmGetCompositionString(m_hIMC, GCS_COMPSTR, buf, 20);
std::wstring wsB=buf;
strCS = ws2s(wsB);
m_compstr = strCS;
dwSize = ImmGetCandidateList(m_hIMC, 0, NULL, 0);
if (dwSize>0)
{
p=new char[dwSize];
lp = (LPCANDIDATELIST)p;
nR = ImmGetCandidateList(m_hIMC, 0, lp, dwSize);
//若是取其它窗口的IMM状态,则lp->dwStyle的值为零(Unknown)。
//否则返回一,表示可以读取lp指向的数据结构!
if (nR && lp->dwCount>1)
{
int i=1;
strCL = "";
char temp[_MAX_BUF_];
ZeroMemory(temp,sizeof(temp));
int nOffset;
while ( (i<lp->dwCount-lp->dwSelection+1) &&
(i<lp->dwPageSize+1) )
{
std::wstring sT= (wchar_t *)(p + lp->dwOffset[lp->dwPageStart+(i-1)]);
sprintf( temp , " %d." , i);
strCL = strCL + temp;
strCL = strCL + "" + ws2s(sT);
i++;
}
if (strCL.find_first_not_of(' ') != -1)
{
strCL =strCL.substr(strCL.find_first_not_of(' '),strCL.length());
//例如“万能五笔输入法中”状态中输入字符"k",strCL变为下值
//1.中 2.口 3.员工maa 4.哎呀aka 5.只w 6.员m
}
}
delete p;
}
else
{
OutputDebugString(L"Error: dwSize = ImmGetCandidateList(hIMC, 0, NULL, 0);<= 0 /n");
}
m_candidate = strCL;
}
//取输入法名称
std::string CGetIme::getDescription()
{
std::string sR("");
m_description = "";
HKL hKL = ::GetKeyboardLayout(0);//获得键盘布局
if (hKL==0)
return sR;
int iSize = ::ImmGetDescription(hKL, NULL, 0);//获得输入法名称大小
if (iSize>=_MAX_BUF_)
{
OutputDebugString(L"CShowIMEUI::getDescription iSize>=MAX_BUF_SIZE CallError/n");
return sR;
}
if (iSize==0)
{
//如果名称大小为0则不显示输入法状态
OutputDebugString(L"CShowIMEUI::getDescription iSize==0 CallError/n");
return sR;
}
wchar_t name[_MAX_BUF_];
::ImmGetDescription(hKL,name, _MAX_BUF_ );//获得输入法名称
std::wstring wsName = name;
sR = ws2s(wsName);
m_description = sR;
return sR;
}
//取输入法状态
std::string CGetIme::getConversion()
{
DWORD dwConversion;
DWORD dwSentence;
LPDWORD lpfdwConversion = &dwConversion;
LPDWORD lpfdwSentence = &dwSentence;
std::string conversion;
m_conversion = "";
if (m_hIMC==NULL)
{
return "";
}
BOOL ret = ::ImmGetConversionStatus(m_hIMC, lpfdwConversion, lpfdwSentence);
::ImmReleaseContext(m_hWnd,m_hIMC);
char pOutputBuf[_MAX_BUF_];
memset(pOutputBuf,0,_MAX_BUF_);
if (*lpfdwConversion & 0x01) strcat(pOutputBuf, " 中文");
else strcat(pOutputBuf, " 英文");
if (*lpfdwConversion & 0x08) strcat(pOutputBuf, " 全角");
else strcat(pOutputBuf, " 半角");
if (*lpfdwConversion & 0x400) strcat(pOutputBuf, " 中文标点");
else strcat(pOutputBuf, " 英文标点");
if (*lpfdwConversion & 0x80) strcat(pOutputBuf, " 软键盘");
else
conversion = "";
conversion = pOutputBuf;
m_conversion = conversion;
return conversion;
}
void CGetIme::disableIME()
{
m_hIMC = ImmAssociateContext(m_hWnd, NULL);
// It makes IME disable for hWnd window.
// Then you can do whatever you want without IME.
//如果是MFC程序~~~~ 最好在 InitInstance() 下加一句~~
//ImmDisableIME(GetCurrentThreadId());
}
void CGetIme::enableIME()
{
ImmAssociateContext(m_hWnd, m_hIMC);
// If you want to enable IME again,
// then you can use the previous stored IME
// context(hIMC) to restore IME.
}
c++实现输入法窗口自定义的代码的更多相关文章
- sublime 自定义快捷代码
选择打开tools ->developer->new snippet <snippet> <content><![CDATA[Hello, ${1:this} ...
- Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8526644 在Android系统中,输入法窗口 ...
- CEGUI 输入法窗口实现
游戏中经常要输入汉字,但当我们游戏没有自己实现输入法窗口时,windows会使用用户安装的输入法,但这个输入法窗口只会显示在游戏窗口外头,而且当我们游戏全屏时(真全屏,不是那种窗口式的假全屏),屏幕上 ...
- 雷林鹏分享:jQuery EasyUI 窗口 - 自定义窗口工具栏
jQuery EasyUI 窗口 - 自定义窗口工具栏 默认情况下,窗口(window)有四个工具:collapsible.minimizable.maximizable 和 closable.比如我 ...
- 雷林鹏分享:jQuery EasyUI 窗口 - 自定义带有工具条和按钮的对话框
jQuery EasyUI 窗口 - 自定义带有工具条和按钮的对话框 您可以创建一个带有工具栏(toolbar)和按钮(button)的对话框(dialog),可以从 HTML 标记创建.这个教程描述 ...
- 自定义sublime代码片段
sublime text 已经有一些他们内置的一些代码片段,但是有时候,这些并不能满足我们,这就需要我们自定义一些代码片段. 步骤如下: 1.打开sublime text 2.选择 tools -&g ...
- sublime自定义snippet代码片段
相信很多人喜欢sublime编辑工具有两个原因:第一sublime很轻巧方便:第二sublime提供很多自定义拓展功能,包括很简单且和很好用的代码片段功能snippet文件. 今天,在这里就介绍下su ...
- 重新想象 Windows 8 Store Apps (27) - 选取器: 联系人选取窗口, 自定义联系人选取窗口
原文:重新想象 Windows 8 Store Apps (27) - 选取器: 联系人选取窗口, 自定义联系人选取窗口 [源码下载] 重新想象 Windows 8 Store Apps (27) - ...
- 重新想象 Windows 8 Store Apps (26) - 选取器: 自定义文件选取窗口, 自定义文件保存窗口
原文:重新想象 Windows 8 Store Apps (26) - 选取器: 自定义文件选取窗口, 自定义文件保存窗口 [源码下载] 重新想象 Windows 8 Store Apps (26) ...
随机推荐
- linux_fedora nexus_auto_start
fedora20发布,不对rc.local支持,其实只是删除了rc.local文件,如果想在开机时能够运行自己写的脚本,只要新建rc.local文件就可以了,下面让我们来测试下吧: 环境:fedo ...
- web.xml中servlet的配置
<servlet>元素是配置Servlet所用的元素. <servlet-mapping>元素在Servlet和URL样式之间定义一个映射,即servlet类提供一个url,在 ...
- UDP TCP 消息边界
先明确一个问题,如果定义了一个数据结构,大小是,比方说 32 个字节,然后 UDP 客户端连续向服务端发了两个包.现在假设这两个包都已经到达了服务器,那么服务端调用 recvfrom 来接收数据,并且 ...
- 基于EBP的栈帧
程序的OEP,一开始以 push ebp 和mov ebp esp这两句开始. 原因:c程序的开始是以一个主函数main()为开始的,而函数在访问的过程中最重要的事情就是要确保堆栈的平衡,而在wi ...
- linq中查询列表的使用及iqueryable和list集合之间的转换
linq中查询列表的使用及iqueryable和list集合之间的转换 比如要查询一个货架集合,但是只需要其id和name即可,可以用以下方法:先写一个model类:CatalogModel(注意该类 ...
- Namespace, string, vector and array
1. Headers should not include using declaration Code inside headers ordinarily should not include us ...
- POJ1328Radar Installation
http://poj.org/problem?id=1328 题的大意就是说在海里有小岛,坐标位置会给出,需要岸边的雷达覆盖所有的小岛,但雷达的覆盖范围有限,所以,需要最少的雷达覆盖所有的小岛,但若是 ...
- 欧拉工程第70题:Totient permutation
题目链接 和上面几题差不多的 Euler's Totient function, φ(n) [sometimes called the phi function]:小于等于n的数并且和n是互质的数的个 ...
- lintcode:Subtree 子树
题目: 子树 有两个不同大小的二叉树: T1 有上百万的节点: T2 有好几百的节点.请设计一种算法,判定 T2 是否为 T1的子树. 样例 下面的例子中 T2 是 T1 的子树: 1 3 / \ / ...
- SULogger:iOS日志可视化工具
前言 debug对于咋们程序员来说家常便饭,但有时候我们会遇到一种情况:开发某个功能时,需要在某个特定场景下进行调试,而这个场景并没有MacBook来进行连接debug,偏偏我们需要获得调试时的一些信 ...