c++windowswinapiime

ImmNotifyIME failed while some IMM functions like ImmGetContext works well


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<LPARAM>(reinterpret_cast<void*>(&cpf)));

While following code failed:

HIMC hImc = fpImmGetContext (hwnd);
fpImmSetCompositionWindow (hImc, &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"Imm32.dll");
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<iace_t>("ImmAssociateContextEx");
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 How to hide the Input Method Editor)

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.


Solution

  • 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().