zoukankan      html  css  js  c++  java
  • 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.
    }

  • 相关阅读:
    python操作redis
    python正则表达式-案例
    hive序列化和反序列化serde
    python配置文件
    Java写入的常用技巧
    Java从string数组创建临时文件
    Java官方操纵byte数组的方式
    python实例方法、静态方法和类方法
    ast.literal_eval(转)
    impala学习笔记
  • 原文地址:https://www.cnblogs.com/yuanxiaoping_21cn_com/p/3687707.html
Copyright © 2011-2022 走看看