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