获取输入法名字

参考来源:https://www.geek-share.com/detail/2680786863.html

我设置在输入法切换,会显示输入法的名称

输出结果:image-20201202221135155

代码如下:

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();  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值