Форум: Форум C++Разное
Новые темы: 00
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум C++

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: HOOK + Эмуляция нажатия клавиш
 
 автор: N0mad   (18.09.2009 в 11:58)   письмо автору
 
 

Есть программа которая эмулирует нажатие клавиш


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 и других задержек.

  Ответить  
 
 автор: cheops   (18.09.2009 в 12:39)   письмо автору
 
   для: N0mad   (18.09.2009 в 11:58)
 

А это всегда воспроизводится, т.е. или виртуальный Shift не нажимается в разнобой, но на одном, то на другом месте?

PS В принципе в этом ничего сверхпорадоксального нет - задержка заложена скорее всего где-то в операционной системе - если со скоростью программы тарабанить по клавиатуре сбои будут и в ручном наборе.

  Ответить  
 
 автор: N0mad   (18.09.2009 в 13:59)   письмо автору
 
   для: cheops   (18.09.2009 в 12:39)
 

всегда в разнобой, иногда и нормально эмулирует, но чем быстрее эмуляция тем больше ошибочных символов которые печатаются с SHIFT'ом.

  Ответить  
 
 автор: N0mad   (18.09.2009 в 14:02)   письмо автору
 
   для: cheops   (18.09.2009 в 12:39)
 

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

  Ответить  
 
 автор: N0mad   (23.09.2009 в 13:16)   письмо автору
 
   для: 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;
}

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования