ImmNotifyIME failed while some IMM functions like ImmGetContext works well

huangapple go评论72阅读模式
英文:

ImmNotifyIME failed while some IMM functions like ImmGetContext works well

问题

我正在使用Windows 10上的IME组合编写程序。
该程序使用DefWindowProc来处理特定线程中的所有WM_IME_消息,并在另一个线程中检查IMM上下文。

当我想要更改输入法的位置时,以下代码运行良好:

HWND idefhwnd = fpImmGetDefaultIMEWnd(hwnd);
::SendMessageW(idefhwnd, WM_IME_CONTROL, IMC_SETCOMPOSITIONWINDOW,
    reinterpret_cast<LPARAM>(reinterpret_cast<void*>(&cpf)));

而以下代码失败了:

HIMC hImc = fpImmGetContext(hwnd);
fpImmSetCompositionWindow(hImc, &cpf);
fpImmReleaseContext(hwnd, hImc);

我想知道是什么情况导致了fpImmNotifyIME失败,或者是否有其他方法可以暂时使候选框不可见。谢谢。

Details:

为了与旧编译器兼容,我使用了以下方式的dll:

hModImm32 = ::GetModuleHandleW(L"Imm32.dll");
fun = ::GetProcAddress(hModImm32, funcname);

某些IMM函数工作正常。我使用ImmAssociateContextEx来暂时禁用IME。它运行良好。

using iace_t = decltype(ImmAssociateContextEx);
iace_t* fpImmAssociateContextEx = mcl_get_immfunc<iace_t>("ImmAssociateContextEx");
if (!fpImmAssociateContextEx) return false;

fpImmAssociateContextEx(hwnd, NULL, IACE_CHILDREN);

但我发现这不能在输入时关闭候选框。因此,在调用fpImmAssociateContextEx之前,我尝试使用以下代码通知输入法在禁用它之前关闭窗口(就像https://stackoverflow.com/questions/70108591/how-to-hide-the-input-method-editor/70111565中的操作一样)。

HIMC himc = fpImmGetContext(hwnd); // himc != nullptr
fpImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
fpImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0);

所有的fpImmNotifyIME都返回了FALSE,并且没有做任何事情。

英文:

I'm writing a program using IME composition on Windows 10.
The program uses DefWindowProc to handle all WM_IME_ message in a specific thread and check IMM context in another thread.

When I want to change the position of input method, the following code works well:

HWND idefhwnd = fpImmGetDefaultIMEWnd (hwnd);
::SendMessageW (idefhwnd, WM_IME_CONTROL, IMC_SETCOMPOSITIONWINDOW,
        reinterpret_cast&lt;LPARAM&gt;(reinterpret_cast&lt;void*&gt;(&amp;cpf)));

While following code failed:

HIMC hImc = fpImmGetContext (hwnd);
fpImmSetCompositionWindow (hImc, &amp;cpf);
fpImmReleaseContext (hwnd, hImc);

I want to know what situation caused fpImmNotifyIME to fail or is there any other way to temporarily make the candidate box invisible. Thanks.

Details:

To be compatible with old compiler, I use dll as follow:

hModImm32 = ::GetModuleHandleW (L&quot;Imm32.dll&quot;);
fun = ::GetProcAddress (hModImm32, funcname);

Some imm functions are working properly. I used ImmAssociateContextEx to disable IME temporarily. It works well.

using iace_t = decltype(ImmAssociateContextEx);
iace_t* fpImmAssociateContextEx = mcl_get_immfunc&lt;iace_t&gt;(&quot;ImmAssociateContextEx&quot;);
if (!fpImmAssociateContextEx) return false;

fpImmAssociateContextEx (hwnd, NULL, IACE_CHILDREN);

But I found out that this cannot close the candidate box when typing. So I'm trying to notify input method to close window when disabling it with following code before fpImmAssociateContextEx is called. (just as https://stackoverflow.com/questions/70108591/how-to-hide-the-input-method-editor/70111565)

HIMC himc = fpImmGetContext (hwnd); // himc != nullptr
fpImmNotifyIME ( himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0 );
fpImmNotifyIME ( himc, NI_CLOSECANDIDATE, 0, 0 );

All fpImmNotifyIME returned FALSE and did nothing.

答案1

得分: 0

问题出在**'程序在一个特定的线程处理消息并在另一个线程中检查IMM上下文。'** ImmNotifyIME()ImmSetCompositionWindow() 默认使用调用这些函数的线程的 HWND。解决方法是通过 SendMessage() 通知负责处理消息循环的线程来调用这些函数。

英文:

The problem lies in 'The program handles message in a specific thread and check IMM context in another thread.' ImmNotifyIME() and ImmSetCompositionWindow() default to using the HWND of the thread calling the functions. The solution is to call these functions by notifying the thread responsible for processing the message loop through SendMessage().

huangapple
  • 本文由 发表于 2023年7月6日 21:21:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76629314.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定