Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: kibsoft от Ноябрь 07, 2012, 00:36



Название: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: kibsoft от Ноябрь 07, 2012, 00:36
В MSDN начитался, что все функции хука должны быть в отдельной библиотеке, но вчера нашел очень простое и быстрое решение:

Код:
#include <QtGui/QApplication>
#include <QDebug>
 
#include <windows.h>
 
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    // process event...
    qDebug() << nCode << wParam << lParam;
 
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
 
    if (SetWindowsHookEx(WH_KEYBOARD_LL, HookProc, qWinAppInst(), NULL) == 0)
        qDebug() << "Hook failed for application instance" << qWinAppInst() << "with error:" << GetLastError();
 
    return a.exec();
}

Оригинальная статься здесь (http://davor.no-ip.com/blog/category/programming/qt/).
Статья в MSDN по хукам(здесь описаны типы и т.д.): Hooks Overview (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644959(v=vs.85).aspx#wh_callwndproc_wh_callwndprocret)


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: navrocky от Ноябрь 07, 2012, 01:09
а теперь докрути еще и реализацию для линуксов, хехе  ;D


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: kibsoft от Ноябрь 07, 2012, 02:03
Судя по документации достаточно переопределить
Код:
bool QApplication::x11EventFilter ( XEvent * event ) [virtual]

Цитировать
If you create an application that inherits QApplication and reimplement this function, you get direct access to all X events that the are received from the X server. The events are passed in the event parameter.

Так что с этим проблем особых нет :)

Еще раз убеждаюсь, что MSDN все-таки не для людей  :D


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: Bepec от Ноябрь 07, 2012, 06:53
kibsoft - а вы уверены, что это сработает в другом приложении?

SetWindowsHookEx ставит хук на ваше приложение. Чтобы же отловить нажатие глобально, необходимо таки как раз собирать библиотеку, которая будет подгружаться к каждому процессу в системе.

PS если я неправ - поправьте. Всегда будет полезен опыт, пользительный аль отрицательный.

PPS хм, интересно. Все же мне кажется это заслуга хука :) К тому же не факт что она будет работать с серьёзными (с защитой) приложениями.

Чисто для справки интересненькая инфа -

Процедура фильтра (hook)  LowLevelKeyboardProc - определяемая программой или определяемая библиотекой функция повторного вызова, используемая функцией SetWindowsHookEx. Система вызывает эту функцию каждый раз, когда собирается вставить новое событие ввода с клавиатуры в очередь ввода данных потока. Ввод с клавиатуры может исходить от локального драйвера клавиатуры или от вызовов функции keybd_event. Если ввод данных исходит из вызова keybd_event, ввод данных  "вставляется". Однако, фильтр (hook)  WH_KEYBOARD_LL не вставляется в другой процесс. Вместо этого, контекст переключается обратно в процесс, который устанавливал фильтр (hook), и  вызывается в его первоначальном контексте. Затем контекст переключается обратно в приложение, которое создало событие.

Тип  HOOKPROC определяет указатель на эту функцию повторного вызова.  LowLevelKeyboardProc - это имя - заместитель для определяемого программой или определяемого библиотекой имени функции.


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: navrocky от Ноябрь 07, 2012, 09:50
Верес прав, я тоже припоминаю теперь что нужна dll. Без нее ничего работать не будет. А то что вы привели для линукс - это вообще не глобальный хук.


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: Bepec от Ноябрь 07, 2012, 10:05
Я прав, но в принципе как простенький хук для "лёгкой" программы предложенный хук сойдёт. Только вот его работоспособность при встрече с защитой под вопросом, как и работоспособность программы с защитой. (как вариант - все ваши нажатия будут отдаваться вашей программе, а возвращаясь будут приниматься текущей программой как подставные данные => фиг что сделаешь.) Хотя это всё лишь додумки мои.

Если честно я даж и незнал, что такой имеется :D


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: ecspertiza от Ноябрь 07, 2012, 11:51
под линь

Код:
bool QApplication::x11EventFilter ( XEvent * event )

нифига не отрабатывает, не приходят события. Тоже приходилось изворачиваться через Api системы :)


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: kibsoft от Ноябрь 07, 2012, 14:09
Цитировать
kibsoft - а вы уверены, что это сработает в другом приложении?
Перед тем как создавать пост я все протестил..все работает :)
Насчет защит не знаю, это надо отдельно проверять.

Код, приведенный в первом посте, рабочий. Достаточно поместить его в main.cpp вашего приложения и посмотреть результат.


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: Bepec от Ноябрь 07, 2012, 14:23
Не беспокойтесь, я проверил до написания своего поста.

И как я уже упомянул - действительно работает. Но судя по нераспространённости этого способа (я о таком не слышал :D ), он или малоизвестен, или имеет подводные камни.

PS но себе на заметку я его взял. Хотя мне проще именно дллку собрать :D


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: Bepec от Ноябрь 14, 2012, 18:09
Кхм. Вопрос к ТСсу - события мышки ты ловить пробовал ?

Поначалу не обратил внимание на название всей темы, но хук WH_KEYBOARD_LL работает исключительно на клавиатуру.

Как вы собираетесь ловить мышку?


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: kibsoft от Ноябрь 14, 2012, 20:48
Я как раз ради мышки это все и затеял. Все работает. Просто надо заменить WH_KEYBOARD_LL на WH_MOUSE_LL.
Поэтому я и дал ссылку на MSDN, где описаны все типы хуков :)


Название: Re: Ловим глобальные события системы с помощью хуков (клавиатура, мышь и т.д.)
Отправлено: Bepec от Ноябрь 14, 2012, 21:04
Кхм, да не будет воспринято вами как страшный наезд, но:

У вас есть тема в разделе "Кладовая готовых решений".
У вас написано в заголовке "мышки и клавы"
У вас имеется пример кода и 2 ссылки.

Я бы сделал вывод, что добрый автор сделал готовое решение и ОООЧЕНЬ долго бы материл автора, который написал в теме про мышку/клаву, а пример сделал только на клаву и то в полусыром виде :)

Мысль сего поста - ну завершите начатое дело.

Пятнадцать минут времени на написание примера кода с ловлей key/mouse(2 hookProc с установкой для разных хуков), с условием
Код:
if (nCode != HC_ACTION )  
return CallNextHookEx(NULL, nCode, wParam, lParam);

модификаторами
Код:
short stateCtrl = GetAsyncKeyState(VK_CONTROL);
short stateShift = GetAsyncKeyState(VK_SHIFT);
short stateCtrl = GetAsyncKeyState(VK_MENU);// ALT
и выводом структуры KBчёто-там и Mouseчёто-там.

+ вывод из этой структуры VK_CODE/position

+ добавление одной ссылки на VirtualKey Code.

И в результате получится действительно готовое решение. А не довольно затруднительный для понимания полуфабрикат :)

PS конечно можете забить на мою гневную отповедь :)