ImmGetContext всегда возвращает ноль

#c #windows #winapi

#c #Windows #winapi

Вопрос:

Я хочу создать корейский регистратор ключей.

Для этого мне нужно проверить режим IME текущего (переднего плана) окна.
Я пытался реализовать это с помощью ImmGetContext функции, но ImmGetContext(GetForegroundWindow()) всегда возвращает ноль.

Как я могу решить эту проблему?

 #include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <immdev.h>
#include <imm.h>
#include <TlHelp32.h>
#pragma comment(lib, "imm32")
using namespace std;

void WINAPI GetProcessNameByProcessID(DWORD dwProcessID, LPWSTR lpszProcessName, size_t nMaxCount) {
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (hSnapshot != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32 processEntry;
        processEntry.dwSize = sizeof(processEntry);
        Process32First(hSnapshot, amp;processEntry);
        do {
            if (processEntry.th32ProcessID == dwProcessID) {
                wcscpy_s(lpszProcessName, nMaxCount, processEntry.szExeFile);
                break;
            }
        } while (Process32Next(hSnapshot, amp;processEntry));
        CloseHandle(hSnapshot);
    }
}

int main() {
    //LoadLibrary(L"imm32.dll");

    while (true) {
        WCHAR szName[100];
        DWORD foregroundProcess;
        HWND foregroundWindow = GetForegroundWindow();
        GetWindowThreadProcessId(foregroundWindow, amp;foregroundProcess);
        GetProcessNameByProcessID(foregroundProcess, szName, 100);
        
        HIMC hIMC;
        DWORD dwConv, dwSent;
        if (!(hIMC = ImmGetContext(foregroundWindow))) return 1; //Error
        ImmSetOpenStatus(hIMC, true);
        ImmGetConversionStatus(hIMC, amp;dwConv, amp;dwSent);

        wcout << szName << L"(" << foregroundProcess << L") : " 
            << (dwConv amp; IME_CMODE_HANGEUL ? L"KOREAN" : L"ENGLISH") << endl;

        ImmReleaseContext(foregroundWindow, hIMC);

        Sleep(1000);
    }
    
    return 0;
}
  

Комментарии:

1. ImmGetContext обычно вызывается в результате для WM_IME_COMPOSITION learn.microsoft.com/en-us/windows/win32/intl / … не уверен, что это работает вне этого и / или вне любого контекста window (ed).

2. @SimonMourier // Спасибо за ваш ответ. Как вы сказали, я попробовал ImmGetContext внутри WndProc, и он работает хорошо. Однако, как и в вопросе, я хочу создать корейский кейлоггер, но использование WndProc не может обрабатывать сообщения от других процессов. Есть ли другой способ? (Я пытался использовать WH_KEYBOARD_LL, но это не работает.)

3. «Это не работает» — это не постановка проблемы.

4. @IInspectable // Я не совсем уверен, как это объяснить. Чтобы быть как можно более подробным, в функции обратного вызова WndProc функция ImmGetContext возвращает ненулевое значение. но в функции обратного вызова LowLevelKeyboardHook функция ImmGetContext возвращает ноль.

Ответ №1:

 #include <iostream>
#include <Windows.h>
#pragma comment (lib, "imm32.lib")
#define IMC_GETOPENSTATUS 0x0005
using namespace std;

int main() {
    while (true) {
        HWND hIME = ImmGetDefaultIMEWnd(GetForegroundWindow());
        LRESULT status = SendMessage(hIME, WM_IME_CONTROL, IMC_GETOPENSTATUS, 0);
        cout << (status ? "Korean" : "English") << endl;
        Sleep(100);
    }
    return 0;
}
  

< Ссылки >

Функция ImmGetDefaultIMEWnd
https://learn.microsoft.com/ko-kr/windows/win32/api/imm/nf-imm-immgetdefaultimewnd

Сообщение WM_IME_CONTROL
https://learn.microsoft.com/en-us/windows/win32/intl/wm-ime-control

IMC_GETOPENSTATUS(0x5) amp; IMC_GETCONVERSIONMODE(0x1)
https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ms920838 (v=msdn.10)
https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ms920931 (v=msdn.10)

IMC_GETOPENSTATUS и IMC_GETCONVERSIONMODE официально не поддерживаются в Windows 10. Однако, похоже, это почти единственный способ реализовать то, что я хочу, и он отлично работает. Я надеюсь, что эта статья полезна. (Google Translate)

Комментарии:

1. Я рад, что вы получили свое решение, и спасибо за то, что поделились, я был бы признателен, если бы вы отметили их как ответ, и это будет полезно для другого сообщества.