#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. Я рад, что вы получили свое решение, и спасибо за то, что поделились, я был бы признателен, если бы вы отметили их как ответ, и это будет полезно для другого сообщества.