Где достать таблицу для:
хардварных сканкодов клавиш? Единая ли она для винды, или же для разных версий дров, клавиатур и т.д. может отличаться?Код:scanCode
Type: DWORD
A hardware scan code for the key.
Вид для печати
Где достать таблицу для:
хардварных сканкодов клавиш? Единая ли она для винды, или же для разных версий дров, клавиатур и т.д. может отличаться?Код:scanCode
Type: DWORD
A hardware scan code for the key.
Scan Code values generated by the PC Keyboard
Не зависит от операционки - эти коды генерит контроллер клавиатуры.Цитата:
Единая ли она для винды, или же для разных версий дров, клавиатур и т.д. может отличаться?
Пока что разбираюсь, как эмулировать зажигание лампочек изнутри функции обработки хука.
Предложенный метод не подходит:
Т.к. он по идее сам и вызовет хук?Код:// Simulate a key press
keybd_event( VK_CAPITAL,
0,
KEYEVENTF_EXTENDEDKEY | 0,
0 );
Попытка внутри хука менять на лету параметр vkCode, scanCode, да и вообще все - на зажигание лампочки НЕ влияет. Влияет если только прервать цепочку хуков по return (1). А мне нужно не прервать, а подменить один код на другой, чтобы заставить принудительно включить или выключить лампочку.
Хук нужен только для того, чтобы пропускать или не пропускать "лампочные" нажатия в Windows. Всё остальное должны делать обычные подпрограммы.
Представим предельно сложную ситуацию, когда клавиша CapsLock и лампочка CapsLock никак друг с другом не связаны - нажатия проходят "мимо лампочки", а лампочка напрямую управляется из программы.
Чтобы хук мог отличить обычные нажатия ( которые он запишет в матрице, но не пропустит в Windows ) и фейк-нажатия (которые в нужный момент генерятся программой специально, чтобы переключить лампочку, и не должны влиять на матрицу нажатых клавиш) - то чтобы хук мог их отличать - нужен всего лишь ещё один флаг для хука, который будет устанавливаться подпрограммой управления лампочкой перед посылкой фейк-нажатия и сбрасываться сразу после этого.
В параметр dwFlags функции keybd_event - там полно места.
---------- Post added 02.01.2013 at 00:03 ---------- Previous post was 01.01.2013 at 23:59 ----------
А можно и прямо в bScan - он там как раз для того, чтобы "общаться" с хуком.
Я уже нашел штатный флаг, который устанавливается при симуляции нажатия - это:
Цитата:
4 Specifies whether the event was injected. The value is 1 if the event was injected; otherwise, it is 0.
Да, в прошлом году я этот флаг тоже нашёл, но за прошедший день упел про него забыть :)
Что-то с хуками все же не чисто.
Все работает, но, когда переключаюсь с эмуляторного окна на окно консоли (которое у меня информационно-отладочное), все жутко начинает тормозить. Даже если в обработчике хука стоит просто переход по цепочке на следующий хук. Убираю хук - все работает быстро.
Пока что загадка.
Быть такого не может - между EXE и DLL нет практически ни какой разницы. Скорее - там где-то Sleep( x ) всех спать отправляет.
---------- Post added at 13:05 ---------- Previous post was at 12:47 ----------
Разборщик сообщений в хук-тесте выглядит так:
Строчка Sleep(1); применена для того, чтобы не отбирать у процессора слишком много времени.Код:dword uTC = GetTickCount();
MSG msg;
for(;;)
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
if( msg.message == WM_QUIT ) break;
}
Sleep(1);
if( GetTickCount() - uTC > 20000 ) { break; }
};
Но при этом - разборщик не может обработать больше 1000 сообщений в секунду. Если сообщений будет приходить больше ( что в данном тесте полностью исключено ) - сообщения перестанут обрабатываться в реальном времени и всё начнёт дико тормозить.
Выяснил, где у меня подтормаживает.
При отладке дебаггером, тормозят две строчки PeekMessage и GetMessage. Причем ТОЛЬКО если есть хук, даже пустой, установленный моей программой. Тормозят где-то по 2-3 секунды каждая, потом программа идет далее.Код:if (PeekMessage(&msg, NULL, 0, 0, 0)) {
if (GetMessage(&msg, NULL, 0, 0)) { // Получить сообщение
TranslateMessage(&msg); // Если сообщение не QUIT,
DispatchMessage(&msg); // оттранслировать его окну
}
else SysExit(); // Иначе выйти закрыв все устройства
}
---------- Post added at 14:15 ---------- Previous post was at 14:09 ----------
Думаю, что дело в хуке.
В режиме, когда подвисают PeekMessage и т.д. (а это когда активно консольное окно эмулятора), функция хука, хотя и установлена, ПЕРЕСТАЕТ работать. Это определяется просто - печатаю в специальное окно сообщение 'Hool action', когда хук вызывается. Так вот в этом режиме оно перестает печататься. Это значит, что функция хука пропадает, и возможно на ней все и подвисает.
---------- Post added at 14:17 ---------- Previous post was at 14:15 ----------
Обработчик хука таков:
Подвисает при активном консольном окне хоть с со строчкой printf, хоть без нее. И прекрасно работает при переключении на окно эмулятора.Код:LRESULT CALLBACK KeyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("Hook action\n");
return CallNextHookEx(hhKeyboardHook, nCode, wParam, lParam);
}
Инициализация хука такая:
Цитата:
hhKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook, hInst, 0); // Установить глобальный хук клавиатуры
Я ни разу не пользовался отладчиком и компилю всегда сразу в Release, поэтому (возможно) с описанными проблемами ни разу не столкнулся.
---------- Post added at 13:26 ---------- Previous post was at 13:24 ----------
Проще ровно в 2 раза ( сообщение извлекается из очереди за один вызов, а не за два ).
А если запустить хук-тест после запуска эмулятора, а потом переключиться в эмулятор ?
Можно сделать два захода - когда эмулятор оставлен в окне эмуляции, а после запуска хук-теста переключается в окно консоли, и наоборот - оставлен в окне консоли, а потом переключается в окно эмуляции.
Можно сделать так, чтобы окно эмуляции устанавливало хук только при получении фокуса, а при потере фокуса - убирало хук..
Но лучше - сделать в эмуляторе ещё одно пустое окно, переключение в которое происходило бы без тормозов - и добавлять туда код реализации консоли, пока тормоза не проявятся.
Хочу для эксперимента сделать в библиотеке.
Есть пример пустой библиотеки? А то VisualC по умолчанию пихает туда какой-то фигни, из-за чего размер 160кб. Причем, фиг отключишь в настройках линкера. Не получилось пока что.
В приложении - статически собранная DLL ( с проектом ), которая при загрузке устанавливает хук и начинает писать лог в файл GlobalHook.log, а при выгрузке - убирает хук и закрывает лог.
Хук будет работать только тогда, когда загрузившая эту DLL программа обрабатывает сообщения.
Так в теории. На практике мне эту DLL грузить нечем, а писать в отдельном проекте ещё и специальный загрузчик - лень.
...
Эм... а 86кб почему?)
Фух, довел хотя бы до 37Кб)
---------- Post added at 16:53 ---------- Previous post was at 16:52 ----------
Слишком много прилинковывается. Разве оно ВСЕ надо? Или это просто стандартный набор?
---------- Post added at 16:54 ---------- Previous post was at 16:53 ----------
Вот ЭТО нужно все?
Цитата:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
---------- Post added at 16:58 ---------- Previous post was at 16:54 ----------
Почему?
Без понятия.
Мне ещё ни разу не удалось заставить работать хук в такой программе, которая не обрабатывает сообщения, или в то время, когда программа почему-то перестаёт обрабатывать сообщения.
---------- Post added at 16:15 ---------- Previous post was at 16:14 ----------
Прилинковывается только тот код, который реально вызывается в DLL.
Прилинковывается та библиотека из этого списка, функции которой используются, остальные нет? Возможно в твоем проекте и так.
А когда я сделал голый проект библиотеки в Вижуал Си, там все было вроде то же самое, но размер итогового файла был 160кб, а у тебя 80кб. Правда, оптимизациями я его уже довел до 37кб, что вообще приемлимо.
Размер важен лишь в смысле размера архива. При запуске файла - Windows просто помечает его как специальный файл подкачки, считывая данные оттуда только при промахе системы виртуальной памяти.
При запуске со съёмных носителей и сетевых приводов - файл EXE считывается целиком и не лочится в качестве файла подкачки.
Поэтому, чтобы после запуска на выполнение гибридных файлов DskExe ( которые я научился делать ровно год назад ) их можно было не только читать, но и писать - надо научиться устанавливать из эмулятора виртуальный файл-сервер и перезапускать эмуляторную часть файла DskExe оттуда.
Какой формат должна иметь какая-либо вызываемая функция в библиотеке, кроме DllMain(), которая инициализирует либу? И в каком виде ее передавать в GetProcAddress() при открытии либы? Прям в таком же добуквенном?
Вот чего интересного нарыл про работу с хуками. Только пока не понял, как сегменту присвоить значение FIXED. И что оно значит вообще.
Цитата:
DLL можно и не загружать если в небольшой программке сделать все сегменты FIXED через def-файл, и там не нужно будет вызывать даже MakeProcInstance - всё будет и так работать.
Судя по тому, что хуки у VisualStudio прекрасно работают из EXE - там всё так и есть.
А зачем это надо в данном случае, когда хук (по идее) должен устанавливаться вызовом LoadLibrary.Цитата:
Какой формат должна иметь какая-либо вызываемая функция в библиотеке, кроме DllMain(), которая инициализирует либу? И в каком виде ее передавать в GetProcAddress() при открытии либы?
Создаётся файл лога после вызова LoadLibrary( "Hook_DLL.dll" ) ?