参考来源:https://www.geek-share.com/detail/2680786863.html
我设置在输入法切换,会显示输入法的名称
输出结果:
代码如下:
TsfApp.h
:
#pragma once
#define _CRT_SECURE_NO_DEPRECATE
#include<windows.h>
#include<WinUser.h>
#include<msctf.h>
#include<stdio.h>
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) \
if(x != NULL) \
{ \
x->Release(); \
x = NULL; \
}
#endif
#ifndef SAFE_ARRAY_DELETE
#define SAFE_ARRAY_DELETE(x) \
if(x != NULL) \
{ \
delete[] x; \
x = NULL; \
}
#endif
struct TsfApp : public ITfUIElementSink, public ITfInputProcessorProfileActivationSink
{
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppvObj);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// ITfUIElementSink
// WM_IME_COMPOSITION、WM_IME_NOTIFY消息的替代者
STDMETHODIMP BeginUIElement(DWORD dwUIElementId, BOOL* pbShow);
STDMETHODIMP UpdateUIElement(DWORD dwUIElementId);
STDMETHODIMP EndUIElement(DWORD dwUIElementId);
// ITfInputProcessorProfileActivationSink
// WM_INPUTLANGUAGECHANGED消息的替代者
STDMETHODIMP OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid,
REFGUID guidProfile, HKL hkl, DWORD dwFlags);
LONG _cRef;
DWORD m_dwUIElementSinkCookie;
DWORD m_dwAlpnSinkCookie;
ITfThreadMgrEx* m_pThreadMgrEx;
ITfInputProcessorProfiles* m_pProfiles;
ITfInputProcessorProfileMgr* _pProfileMgr;
HRESULT SetupSinks();
HRESULT ReleaseSinks();
wchar_t* GetCurrentIMEName();
};
TsfApp.cpp
#define _CRT_SECURE_NO_DEPRECATE
#include "TsfApp.h"
#include <assert.h>
#include <locale.h>
HRESULT TsfApp::SetupSinks()
{
CoInitialize(NULL);
HRESULT hr;
hr = CoCreateInstance(CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ITfThreadMgrEx),
(void**)&m_pThreadMgrEx);
if (FAILED(hr))
{
return hr;
}
TfClientId cid;
if (FAILED(hr = m_pThreadMgrEx->ActivateEx(&cid, TF_TMAE_UIELEMENTENABLEDONLY)))
{
return hr;
}
ITfSource* srcTm;
if (SUCCEEDED(hr = m_pThreadMgrEx->QueryInterface(__uuidof(ITfSource), (void**)&srcTm)))
{
srcTm->AdviseSink(__uuidof(ITfUIElementSink), (ITfUIElementSink*)this, &m_dwUIElementSinkCookie);
srcTm->AdviseSink(__uuidof(ITfInputProcessorProfileActivationSink), (ITfInputProcessorProfileActivationSink*)this, &m_dwAlpnSinkCookie);
srcTm->Release();
}
else
return hr;
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles, (LPVOID*)&m_pProfiles);
if (FAILED(hr))
return hr;
m_pProfiles->QueryInterface(IID_ITfInputProcessorProfileMgr, (void**)&_pProfileMgr);
return S_OK;
}
HRESULT TsfApp::ReleaseSinks()
{
CoInitialize(NULL);
HRESULT hr;
hr = CoCreateInstance(CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ITfThreadMgrEx),
(void**)&m_pThreadMgrEx);
if (FAILED(hr))
{
return hr;
}
ITfSource* srcTm;
if (SUCCEEDED(hr = m_pThreadMgrEx->QueryInterface(__uuidof(ITfSource), (void**)&srcTm)))
{
srcTm->UnadviseSink(m_dwUIElementSinkCookie);
srcTm->UnadviseSink(m_dwAlpnSinkCookie);
srcTm->Release();
}
else
return hr;
}
STDAPI TsfApp::QueryInterface(REFIID riid, void** ppvObj)
{
if (ppvObj == NULL)
return E_INVALIDARG;
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown))
*ppvObj = reinterpret_cast<IUnknown*>(this);
else if (IsEqualIID(riid, __uuidof(ITfUIElementSink)))
*ppvObj = (ITfUIElementSink*)this;
else if (IsEqualIID(riid, __uuidof(ITfInputProcessorProfileActivationSink)))
*ppvObj = (ITfInputProcessorProfileActivationSink*)this;
else if (IsEqualIID(riid, __uuidof(ITfLanguageProfileNotifySink)))
*ppvObj = (ITfLanguageProfileNotifySink*)this;
if (*ppvObj)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDAPI_(ULONG) TsfApp::AddRef()
{
return ++_cRef;
}
STDAPI_(ULONG) TsfApp::Release()
{
LONG cr = --_cRef;
assert(_cRef >= 0);
if (_cRef == 0)
delete this;
return cr;
}
STDAPI TsfApp::BeginUIElement(DWORD dwUIElementId, BOOL* pbShow)
{
/* 设置为FALSE表示隐藏UI */
*pbShow = FALSE;
return S_OK;
}
STDAPI TsfApp::UpdateUIElement(DWORD dwUIElementId)
{
ITfUIElementMgr* lpMgr = NULL;
ITfCandidateListUIElement* lpCandUI = NULL;
ITfReadingInformationUIElement* lpReading = NULL;
ITfUIElement* pElement = NULL;
/* 获取候选词或组合词 */
if (SUCCEEDED(m_pThreadMgrEx->QueryInterface(IID_ITfUIElementMgr, (void**)&lpMgr)))
{
if (SUCCEEDED(lpMgr->GetUIElement(dwUIElementId, &pElement)))
{
if (SUCCEEDED(pElement->QueryInterface(IID_ITfCandidateListUIElement, (void**)&lpCandUI)))
{
BSTR _sss;
lpCandUI->GetString(0, &_sss);
SysFreeString(_sss);
SAFE_RELEASE(lpCandUI);
}
if (SUCCEEDED(pElement->QueryInterface(IID_ITfReadingInformationUIElement, (void**)&lpReading)))
{
BSTR _sss;
lpReading->GetString(&_sss);
SysFreeString(_sss);
SAFE_RELEASE(lpReading);
}
SAFE_RELEASE(pElement);
}
SAFE_RELEASE(lpMgr);
}
return S_OK;
}
STDAPI TsfApp::EndUIElement(DWORD dwUIElementId)
{
ITfDocumentMgr* pDocMgr = NULL;
ITfContext* pContex = NULL;
ITfContextView* pContexView = NULL;
HWND hActiveHwnd = NULL;
if (SUCCEEDED(m_pThreadMgrEx->GetFocus(&pDocMgr)))
{
if (SUCCEEDED(pDocMgr->GetTop(&pContex)))
{
if (SUCCEEDED(pContex->GetActiveView(&pContexView)))
{
pContexView->GetWnd(&hActiveHwnd);
SAFE_RELEASE(pContexView);
}
SAFE_RELEASE(pContex);
}
SAFE_RELEASE(pDocMgr);
}
if (NULL != hActiveHwnd)
{
SendMessageW(hActiveHwnd, WM_IME_NOTIFY, IMN_CLOSECANDIDATE, 0);
}
return S_OK;
}
STDAPI TsfApp::OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid,
REFGUID guidProfile, HKL hkl, DWORD dwFlags)
{
bool bActive = (dwFlags & TF_IPSINK_FLAG_ACTIVE);
if (!bActive)
return S_OK;
if (dwProfileType & TF_PROFILETYPE_INPUTPROCESSOR)
{
/* 输入法是 TIP */
printf("TIP输入法 [%08X]\n", (unsigned int)hkl);
}
else if (dwProfileType & TF_PROFILETYPE_KEYBOARDLAYOUT)
{
/* 当前输入法是键盘布局或IME */
printf("HKL/IME %08X\n", (unsigned int)hkl);
}
else
{
/* 不可能走到这里 */
printf("dwProfileType unknown!!!\n");
}
wchar_t* c = GetCurrentIMEName();
setlocale(LC_ALL, "");
printf("输入法名称:%ls\n", c);
return S_OK;
}
/* 获取HKL的显示名字
*/
bool GetLayoutName(const wchar_t* kl, wchar_t* nm)
{
long lRet;
HKEY hKey;
static wchar_t tchData[64];
DWORD dwSize;
wchar_t keypath[200];
wsprintfW(keypath, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", kl);
lRet = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
keypath,
0,
KEY_QUERY_VALUE,
&hKey
);
if (lRet == ERROR_SUCCESS)
{
dwSize = sizeof(tchData);
lRet = RegQueryValueExW(
hKey,
L"Layout Text",
NULL,
NULL,
(LPBYTE)tchData,
&dwSize
);
}
RegCloseKey(hKey);
if (lRet == ERROR_SUCCESS && wcslen(nm) < 64)
{
wcscpy(nm, tchData);
return true;
}
return false;
}
/* 获取当前输入法名字
*/
wchar_t* TsfApp::GetCurrentIMEName()
{
static wchar_t _LastTipName[64];
ZeroMemory(_LastTipName, sizeof(_LastTipName));
TF_INPUTPROCESSORPROFILE tip;
_pProfileMgr->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD, &tip);
if (tip.dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR)
{
BSTR bstrImeName = NULL;
m_pProfiles->GetLanguageProfileDescription(tip.clsid, tip.langid, tip.guidProfile, &bstrImeName);
if (wcslen(bstrImeName) < 64)
wcscpy(_LastTipName, bstrImeName);
SysFreeString(bstrImeName);
}
else if (tip.dwProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT)
{
static wchar_t klnm[KL_NAMELENGTH];
if (GetKeyboardLayoutNameW(klnm))
{
GetLayoutName(klnm, _LastTipName);
}
}
return _LastTipName;
}
调用方法:
TsfApp* app= new TsfApp();
app->SetupSinks();
// 主窗口事件循环。
app->ReleaseSinks(); //释放注册
输出均在命令行,如果未开启命令行可以使用以下代码开启命令行:
HANDLE hOutput;
void console_init(void)
{
AllocConsole();
SetConsoleTitle(L"Debug Window");
SetConsoleCtrlHandler(NULL, true);
freopen("CONOUT$", "w", stdout);
//FreeConsole();
}
记得最后关闭命令行窗口:
FreeConsole();