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) ...
随机推荐
- vi 常用技巧
vi/vim : Visual Interface/VI iMproved VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需 ...
- plsql 使用技巧
问题1: 每次打开plsql 布局都被恢复还原了. 你可以调整好一个布局,然后window ->Save Lay out 即可
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结 ...
- ASP.NET WebAPI2 发布之后404 Note Found
方法一:首先确保服务器安装.Net FrameWork 4.0 并且注册IIS 如果先安装.net framework4.0,再安装IIS,则会出现4.0的ISAPI没有注册的情况. 运行:C:\Wi ...
- winform中的checkedListbox数据源绑定
首先看清楚一点 winform下该控件的名称叫做:checkedListbox webform下叫做CheckBoxList 不知道这样起名的用意何在,这个别管了,看看用法吧. web下很简单,直接设 ...
- Selenium如何使用自定义的Firefox配置文件?
一.自动保存文件 import os from selenium import webdriver fp = webdriver.FirefoxProfile() fp.set_preference( ...
- Rockethon 2015
A Game题意:A,B各自拥有两堆石子,数目分别为n1, n2,每次至少取1个,最多分别取k1,k2个, A先取,最后谁会赢. 分析:显然每次取一个是最优的,n1 > n2时,先手赢. 代码: ...
- 日期工具类TimeUnit
import java.util.concurrent.TimeUnit; 2 3 public class TimeUnitDemo { 4 private TimeUnit timeUnit =T ...
- HTML5入门5---HTML5控件元素
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 使用Retrofit时出现 java.lang.IllegalArgumentException: URL query string "t={type}&p={page}&size={count}" must not have replace block. For dynamic query parameters use @Query.异常原因
/** * Created by leo on 16/4/30. */ public interface GanchaiService { @GET("digest?t={type}& ...