Здравствуйте, Carc, Вы писали:
C>2) Судя по незабвенной константе WH_KEYBOARD_LL хук глобальный и только, и иначе быть не может, значит должен быть в DLL. C>Но судя по строке C>HMODULE hInstance = GetModuleHandle(NULL) из функции SetKeyboardHook C>получаем HMODULE exe-шника вызывающего процесса!?! И пытаетесь сказать системе, что процедура глобального хука в exe-шнике? По уму, хук вообще вроде как не должен ставиться...
WH_KEYBOARD_LL в этом смысле -- исключение.
The LowLevelKeyboardProc hook procedure is an application-defined or library-defined callback function [...] However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.
void CfgdfgDlg::OnBnClickedButton1()
{
int Len, DropLen;
CString buffDroped;
WORD w;
//Строка которую мы будем эмулировать
buffDroped = TEXT("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
DropLen = buffDroped.GetLength();
for (int i=0;i<DropLen;i++)
{
Len = buffDroped.GetLength();
if (Len>i)
{
w = VkKeyScan(buffDroped[i]);
if ((HIBYTE(w) != 0xFF) && (LOBYTE(w) != 0xFF))
{
if (HIBYTE(w))
{
keybd_event(VK_SHIFT, 0, 0, 0);
//Sleep(50);
}
keybd_event(LOBYTE(w),0,0,0);
keybd_event(LOBYTE(w),0,KEYEVENTF_KEYUP,0);
if (HIBYTE(w))
{
keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
}
}
}
}
}
и программа которая ловит нажатие клавиш (HOOK)
HHOOK hKeyHook = NULL;
WORD GetSymbolFromVK(WPARAM wParam, UINT scanecode)
{
BYTE btKeyState[256];
HKL hklLayout = GetKeyboardLayout(0);
WORD Symbol = NULL;
GetKeyboardState(btKeyState);
if ((ToAsciiEx(wParam, scanecode, btKeyState, &Symbol, 0, hklLayout) == 1) &&
(GetKeyState(VK_CONTROL) >= 0) && (GetKeyState(VK_MENU) >= 0))
return Symbol;
return -1;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
WORD wc = 0;
if (nCode >= HC_ACTION)
{
//Если действие было - нажатие кнопочки
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
{
//Получаем символ
if ((wc = GetSymbolFromVK(((PKBDLLHOOKSTRUCT)lParam)->vkCode, ((PKBDLLHOOKSTRUCT)lParam)->scanCode)) != -1)
{
//Проверяем если он печатемый
if (iswprint(wc))
{
//обработка символа
}
}
}
}
return CallNextHookEx(hKeyHook, nCode, wParam, lParam);
}
BOOL SetKeyboardHook(BOOL Hook)
{
HMODULE hInstance = GetModuleHandle(NULL);
if (Hook)
{
hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyboardProc, hInstance, NULL);
return (hKeyHook != NULL);
}
else
{
UnhookWindowsHookEx(hKeyHook);
hKeyHook = NULL;
return (hKeyHook != NULL);
}
}
При перехвате нажатий клавиш с клавиатуры всё работает как надо, а при перехвате эмуляции клавиш иногда возникают проблемы с сиволами которые печатаются с клавишей "SHIFT" т.е.: !"№;%:?*() и тд.
Например если мы будем эмулировать строку !!23456789??
то наш hook ловит и преобразовывает их в символы !1@3456789/?
SHIFT пременился не для второго символа а для третьего и для предпоследнего он не применился(((, а если после эмуляции нажатия SHIFT поставить Sleep(50); то всё нормально. Но Sleep не есть good!! Как можно обойтись без Sleep и других задержек.
16.09.09 20:59: Перенесено модератором из 'C/C++' — Кодт
Задам вопрос иначе!! Когда замедляешь скорость эмуляции то всё работает нормально, и хук обрабатывает всё корректно!! Но без задержки символы с SHIFT'ом печатаются неправельно, как будто хук не успевает обрабатывать большую скорость эмуляции, но по идее там всё работать должно последовательно и таких глюков быть не должно!!
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, N0mad, Вы писали:
N>>Есть программа которая эмулирует нажатие клавиш
PD>А если вместо keybd_event попробовать SendInput ?
Просто здесь дело не в том как мы будем эмулировать, а в от как мы будем реализовывать хук, с эмуляцией проблем нет, если выключить хук и эмулировать строку без слипов то всё прекрасно работает, включаем хук, и на перехвате мы получаем то что получаем
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, N0mad, Вы писали:
N>>Есть программа которая эмулирует нажатие клавиш
PD><skipped>
PD>А если вместо keybd_event попробовать SendInput ?
2Pavel:
А разве keybd_event в 2к и выше не юзает SendInput?
MSDN:
keybd_event
...
Windows NT/2000 or later: This function has been superseded. Use SendInput instead.
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Здравствуйте, N0mad, Вы писали:
N>>>Есть программа которая эмулирует нажатие клавиш
PD>><skipped>
PD>>А если вместо keybd_event попробовать SendInput ?
C>2Pavel: C>А разве keybd_event в 2к и выше не юзает SendInput? C>
C>MSDN:
C>keybd_event
C>...
C>Windows NT/2000 or later: This function has been superseded. Use SendInput instead.
Даже если и так, то это нам ничего не даёт, ещё раз повторюсь, проблема не в эмуляции, проблема в хуке.
PD>>>А если вместо keybd_event попробовать SendInput ?
C>>2Pavel: C>>А разве keybd_event в 2к и выше не юзает SendInput? C>>
C>>MSDN:
C>>keybd_event
C>>...
C>>Windows NT/2000 or later: This function has been superseded. Use SendInput instead.
WJI>Даже если и так, то это нам ничего не даёт, ещё раз повторюсь, проблема не в эмуляции, проблема в хуке.
1) При эмуляции "сэмулированная строка" по идее должна пойти в приложение имеющее фокус ввода, не может быть с этим какой-то заморочки?
Особенно настараживает CfgdfgDlg::OnBnClickedButton1, т.е. судя по названию, т.е. эмулируем вроде как по нажатию кнопки? Значит фокус ввода на кнопке. Следовательно, значит прога сама себе и симулирует строку!?!
2) Судя по незабвенной константе WH_KEYBOARD_LL хук глобальный и только, и иначе быть не может, значит должен быть в DLL.
Но судя по строке
HMODULE hInstance = GetModuleHandle(NULL) из функции SetKeyboardHook
получаем HMODULE exe-шника вызывающего процесса!?! И пытаетесь сказать системе, что процедура глобального хука в exe-шнике? По уму, хук вообще вроде как не должен ставиться...
Здравствуйте, N0mad, Вы писали:
N>Задам вопрос иначе!! Когда замедляешь скорость эмуляции то всё работает нормально, и хук обрабатывает всё корректно!! Но без задержки символы с SHIFT'ом печатаются неправельно, как будто хук не успевает обрабатывать большую скорость эмуляции, но по идее там всё работать должно последовательно и таких глюков быть не должно!!
Из MSDN вроде как следует что хук хватает инфу когда она помещается в очередь!?! Поэтому по идее, что там было, то он и вынул оттуда... Может быть попробовать все таки эмулятор вытащить из обработчика кнопки? Ну к примеру повесить его на WM_HOTKEY: и соответственно регаем клавишу, потом нажимаем ее, и приложение начинает эмулять строчку. При WM_HOTKEY фокус ввода где был, там и останется... Имхо, стоит попробовать для чистоты эксперимента !?!
Здравствуйте, quodum, Вы писали:
Q>Здравствуйте, Carc, Вы писали:
C>>2) Судя по незабвенной константе WH_KEYBOARD_LL хук глобальный и только, и иначе быть не может, значит должен быть в DLL. C>>Но судя по строке C>>HMODULE hInstance = GetModuleHandle(NULL) из функции SetKeyboardHook C>>получаем HMODULE exe-шника вызывающего процесса!?! И пытаетесь сказать системе, что процедура глобального хука в exe-шнике? По уму, хук вообще вроде как не должен ставиться...
Q>WH_KEYBOARD_LL в этом смысле -- исключение.
Q>
The LowLevelKeyboardProc hook procedure is an application-defined or library-defined callback function [...] However, the WH_KEYBOARD_LL hook is not injected into another process. Instead, the context switches back to the process that installed the hook and it is called in its original context. Then the context switches back to the application that generated the event.
(c) MSDN, LowLevelKeyboardProc Function
СПАСИБО!!! +2
И в правду все работает даже и из exe-шника... А я когда-то по молодости повелся на тип хука "Global Only" и с тех пор даже и не пытался!
Век живи — век учись!
C>Из MSDN вроде как следует что хук хватает инфу когда она помещается в очередь!?! Поэтому по идее, что там было, то он и вынул оттуда... Может быть попробовать все таки эмулятор вытащить из обработчика кнопки? Ну к примеру повесить его на WM_HOTKEY: и соответственно регаем клавишу, потом нажимаем ее, и приложение начинает эмулять строчку. При WM_HOTKEY фокус ввода где был, там и останется... Имхо, стоит попробовать для чистоты эксперимента !?!
Ну в силу поста ниже
Нашёл в чем дело. Проблема была в функции GetKeyboardState().
Замечания к функии
Прикладная программа может вызвать эту функцию, чтобы извлечь данные о текущем состоянии всех виртуальных клавиш. Состояние изменяется тогда, когда поток удаляет сообщения клавиатуры из ее очереди сообщений. Состояние не изменяется тогда, когда сообщения клавиатуры посланы в очередь сообщений.
Видимо поток не успевал удалять сообщение из очереди.
Решил это так