crumbcube
@crumbcube

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

アクティブウインドウのIMEの状態判定

解決したいこと

Windows11におけるWin32プログラミング環境での質問です。
アクティブウインドウのIMEがオンかオフかを判断しようとしていますが、なぜかメモ帳がアクティブの場合に限ってその判断ができません。

発生している問題・エラー

IMEのオンとオフを繰り返しても常に0でオフ状態が返ってきます。

該当するソースコード

    HWND foreground = GetForegroundWindow();
    if (foreground == NULL) {
        return;
    }

    HWND hIMEWnd = ImmGetDefaultIMEWnd(foreground);
    if (hIMEWnd == NULL) {
        OutputDebugStringW(L"Failed to get IME window\n");
        return;
    }

    LRESULT imeStatus = SendMessageA(hIMEWnd, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0);

    if (imeStatus) {
        wcscpy_s(nid.szTip, _countof(nid.szTip), L"IME: ON");
    }
    else {
        wcscpy_s(nid.szTip, _countof(nid.szTip), L"IME: OFF");
    }

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。

0

3Answer

GetForegroundWindow()で取得したメモ帳の(メイン)ウィンドウハンドルから、EnumChildWindows()等で、RichEditの子ウィンドウのハンドルを取得して、そのハンドルでImmGetDefaultIMEWnd()すると、正しくIMEの状態を判定できます。

g2.png

↑スクショを例にすると、GetForegroundWindow()で取得したメモ帳の(メイン)ウィンドウハンドルは0x0404D0。このハンドルでは、IMEの状態を正しく判定きない。
メモ帳の子(孫)ウィンドウの0x02060Cに対してImmGetDefaultIMEWnd()すると、正しくIMEの状態を判定できる。
(メモ帳のタブごとに、RichEditD2DPTウィンドウクラスのウィンドウが作られる)

0Like

Comments

  1. @crumbcube

    Questioner

    EnumChildWindows()で、RichEditの子ウィンドウのハンドルを取得できた場合、RichEditD2DPTクラスもIMEチェック対象にし、そのハンドルでImmGetDefaultIMEWnd()することで、正しくIMEの状態を判定することができました。

GetGUIThreadInfoを使えば実際にフォーカスが当たってるウィンドウハンドルが取れるので、そっちを使いましょう

    GUITHREADINFO guiThreadInfo = { sizeof(GUITHREADINFO) };
    if (!::GetGUIThreadInfo(0, &guiThreadInfo)) {
        return 0;   // failed
    }
    HWND hwndDefaultIME = ::ImmGetDefaultIMEWnd(guiThreadInfo.hwndFocus);
    bool imeEnabled = (::SendMessage(hwndDefaultIME, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0) != 0);
0Like

こんなに簡潔に判定できるのですね。大変勉強になりました。
GUITHREADINFO guiThreadInfo = { sizeof(GUITHREADINFO) };

// GUI スレッド情報を取得
if (!GetGUIThreadInfo(0, &guiThreadInfo)) {
    OutputDebugStringW(L"Failed to get GUI thread info\n");
    return;
}

// フォーカスウィンドウのデフォルトIMEウィンドウを取得
HWND hwndDefaultIME = ImmGetDefaultIMEWnd(guiThreadInfo.hwndFocus);
if (hwndDefaultIME == NULL) {
    OutputDebugStringW(L"Failed to get default IME window\n");
    return;
}

// IMEのオン・オフ状態を取得
LRESULT imeStatus = SendMessageW(hwndDefaultIME, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0);
0Like

Your answer might help someone💌