|
|
|
| Есть программа которая эмулирует нажатие клавиш
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 и других задержек. | |
|
|
|
|
|
|
|
для: N0mad
(18.09.2009 в 11:58)
| | А это всегда воспроизводится, т.е. или виртуальный Shift не нажимается в разнобой, но на одном, то на другом месте?
PS В принципе в этом ничего сверхпорадоксального нет - задержка заложена скорее всего где-то в операционной системе - если со скоростью программы тарабанить по клавиатуре сбои будут и в ручном наборе. | |
|
|
|
|
|
|
|
для: cheops
(18.09.2009 в 12:39)
| | всегда в разнобой, иногда и нормально эмулирует, но чем быстрее эмуляция тем больше ошибочных символов которые печатаются с SHIFT'ом. | |
|
|
|
|
|
|
|
для: cheops
(18.09.2009 в 12:39)
| | Я тоже думаю если по клаве печатать со скоростью эмуляции то глюки тоже будут, но почему вообще такие глюки возникают ведь там всё ставится в очередь и последовательно обрабатывается, по идее таких глюков то быть и не должно, и теперь думай как это исправить без задержек. | |
|
|
|
|
|
|
|
для: N0mad
(18.09.2009 в 11:58)
| | Нашёл в чем дело. Проблема была в функции GetKeyboardState().
Замечания к функии
Прикладная программа может вызвать эту функцию, чтобы извлечь данные о текущем состоянии всех виртуальных клавиш. Состояние изменяется тогда, когда поток удаляет сообщения клавиатуры из ее очереди сообщений. Состояние не изменяется тогда, когда сообщения клавиатуры посланы в очередь сообщений.
Видимо поток не успевал удалять сообщение из очереди.
Решил это так
void ProcessMessage()
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
return;
}
}
WORD GetSymbolFromVK(WPARAM wParam, UINT scanecode)
{
BYTE btKeyState[256];
HKL hklLayout = GetKeyboardLayout(0);
TCHAR Symbol = NULL;
//LoadKeyboardLayout(TEXT("00000409"), KLF_ACTIVATE);
ProcessMessage();
GetKeyboardState(btKeyState);
if ((ToUnicodeEx(wParam, scanecode, btKeyState, &Symbol, 1, 0, hklLayout) == 1) && // сам перевод
(GetKeyState(VK_CONTROL) >= 0) && (GetKeyState(VK_MENU) >= 0))
{
return Symbol;
}
return -1;
} | |
|
|
|