TSF(Text Service Framework)中如何禁止输入法

YU Coat 0 信誉分
2024-07-31T07:06:15.5133333+00:00

我使用win32 api创建了一个很简单的窗口。窗口展示后将输入法切换至中文并敲击键盘字母,此时屏幕左上角会出现IME的选词窗口(如下所示:)

无标题

在上图这种情况里,我想通过代码动态地禁用(或启用)输入法。当禁用之后,即使切换为中文输入法,敲击字母按键也不出现选词框,当启用输入法之后,一切照旧。

为了达到目的,我查阅了一些资料,发现imm32的api能达到这一效果

::ImmAssociateContextEx(m_hWnd, NULL, 0);

假如我不想调用imm32,而是使用tsf,那么该如何实现禁止输入法呢?

我参考了chromium的代码,尝试着在代码中使用了以下方法禁用输入法,结果并没有效果:

HRESULT TSFBridgeImpl::InitializeDisabledContext(ITfContext* context) {
  Microsoft::WRL::ComPtr<ITfCompartmentMgr> compartment_mgr;
  HRESULT hr = context->QueryInterface(IID_PPV_ARGS(&compartment_mgr));
  if (FAILED(hr)) {
    return hr;
  }

  Microsoft::WRL::ComPtr<ITfCompartment> disabled_compartment;
  hr = compartment_mgr->GetCompartment(GUID_COMPARTMENT_KEYBOARD_DISABLED,
                                       &disabled_compartment);
  if (FAILED(hr)) {
    return hr;
  }

  base::win::ScopedVariant variant;
  variant.Set(1);
  hr = disabled_compartment->SetValue(client_id_, variant.ptr());
  if (FAILED(hr)) {
    return hr;
  }

  Microsoft::WRL::ComPtr<ITfCompartment> empty_context;
  hr = compartment_mgr->GetCompartment(GUID_COMPARTMENT_EMPTYCONTEXT,
                                       &empty_context);
  if (FAILED(hr)) {
    return hr;
  }
  base::win::ScopedVariant empty_context_variant;
  empty_context_variant.Set(static_cast<int32_t>(1));
  hr = empty_context->SetValue(client_id_, empty_context_variant.ptr());
  if (FAILED(hr)) {
    return hr;
  }

  return S_OK;
}

所以想请教一下,我的TSF禁用输入法的思路是否正确,如果正确,问题出在哪里?如果不正确,又该如何实现?

Windows API - Win32
Windows API - Win32
一组适用于桌面和服务器应用程序的核心 Windows 应用程序编程接口 (API)。 以前称为 Win32 API。
98 个问题
0 个注释 无注释
{count} 票

1 个答案

排序依据: 非常有帮助
  1. Xiaopo Yang - MSFT 12,726 信誉分 Microsoft 供应商
    2024-08-01T02:36:10.4+00:00

    您好 @YU Coat,

    我也不能让ITfCompartment禁止输入法。我觉得TSF(Text Service Framework)是有能力做到这一点的,或许你可以参考一下这个程序https://github.com/ryancheung/ImeSharp.

    {
        CoInitialize(NULL);
        // An identifier of TSF client.
        TfClientId client_id_ = TF_CLIENTID_NULL;
        HRESULT hr;
        ITfThreadMgr* thread_manager_;
        hr = CoCreateInstance(CLSID_TF_ThreadMgr,
            NULL,
            CLSCTX_ALL,
            IID_ITfThreadMgr,
            (void**)&thread_manager_);
        if (FAILED(thread_manager_->Activate(&client_id_))) {
            return 1;
        }
        ITfDocumentMgr* document_manager;
        if (FAILED(thread_manager_->CreateDocumentMgr(&document_manager))) {
            return false;
        }
        DWORD edit_cookie = TF_INVALID_EDIT_COOKIE;
        ITfContext* context;
        if (FAILED((document_manager)
            ->CreateContext(client_id_, 0,
                NULL,
                &context, &edit_cookie))) {
            return false;
        }
        if (FAILED((document_manager)->Push(context))) {
            return false;
        }
        ITfCompartmentMgr* compartment_mgr;
        if (FAILED(context->QueryInterface(IID_PPV_ARGS(&compartment_mgr)))) {
            return false;
        }
        ITfCompartment* empty_context;
        if (FAILED(compartment_mgr->GetCompartment(GUID_COMPARTMENT_EMPTYCONTEXT,
            &empty_context))) {
            return false;
        }
        VARIANT empty_context_variant{};
        empty_context_variant.vt = VT_I4;
        empty_context_variant.bVal = 1;
        if (FAILED(
            empty_context->SetValue(client_id_, &empty_context_variant))) {
            return false;
        }
        ITfCompartment* disabled_compartment;
        if (FAILED(compartment_mgr->GetCompartment(
            GUID_COMPARTMENT_KEYBOARD_DISABLED,
            &disabled_compartment))) {
            return false;
        }
        VARIANT variant{};
        variant.vt = VT_I4;
        variant.bVal = 1;
        if ((hr = (disabled_compartment->SetValue(client_id_, &variant))) != S_OK) {
            return false;
        }
    }
    
    0 个注释 无注释

你的答案

问题作者可以将答案标记为“接受的答案”,这有助于用户了解已解决作者问题的答案。