Форум: "Основная";
Текущий архив: 2006.10.15;
Скачать: [xml.tar.bz2];
ВнизПерехват нажатий клавиш в системе. Найти похожие ветки
← →
SUN_ALF © (2006-08-26 23:25) [0]Доброго времени суток, господа!
Писал "ловушку" для нажатий клавиш в системе. Тестовый вариант (полностью текст библиотеки вместе с процедурой установки ловушки на листинге 1) выдавал забавный результат: на одно нажатие пробела (даже самое короткое и молниеносное :) ) выскакивали сразу два окошка МессэджБокса. Потом попробовал (листинг 2) изменить принимаемое сообщение, то есть параметр wParam, в котором хранится код нажатой клавиши. Я хотел, чтобы ловушка меняла код нажатой клавиши на код восклицательного знака (33), но результат получился нулевой: любой текстовый редактор принимал ровно тот символ, который я нажимал на клаве.
Подскажите, пожалуйста, где закопаны грабли и как их разминировать?
---------------------------------------------------
ЛИСТИНГ 1:
library KeyboardHook;
uses Windows, Messages;
var
KeyHook: HHook = 0;
handle: HWnd;
Function OnKeyHook(code: ShortInt; wParam: Word; lParam: Longint): Longint stdcall;
Begin
if code = HC_ACTION then
begin
if wParam = 32 then
begin
MessageBox(0, Pchar("space!!!"), Pchar("Принято:"), MB_OK);
end;
end;
Result:= CallNextHookEx(KeyHook, code, wParam, lParam);
End;
Procedure HookLauncher(code: Byte); export; stdcall;
Begin
if BOOL(code) then
KeyHook:= SetWindowsHookEx(WH_KEYBOARD, @OnKeyHook, HInstance, 0)
else
begin
UnhookWindowsHookEx(KeyHook);
KeyHook:= 0;
end;
End;
exports HookLauncher;
BEGIN
END.
----------------------------------------------------------
ЛИСТИНГ 2:
Function OnKeyHook(code: ShortInt; wParam: Word; lParam: Longint): Longint stdcall;
Begin
if code = HC_ACTION then
begin
if wParam = 32 then
begin
wParam:= 33;
end;
end;
Result:= CallNextHookEx(KeyHook, code, wParam, lParam);
End;
-----------------------------------------------------
← →
Ketmar © (2006-08-26 23:31) [1]> где закопаны грабли и как их разминировать?
документацию читать, а не Флёнова. %-) хуки так не пишут. %-)
и вообще -- поискать, ибо подобные темы муссировались неоднократно.
зыж за правильно заданый вопрос -- +1. за нежелание искать самому -- -1. %-)
← →
Zeqfreed © (2006-08-26 23:31) [2]
If code is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx.
. . .Return Values
To prevent Windows from passing the message to the rest of the hook chain or to the target window procedure, the return value must be a nonzero value. To allow Windows to pass the message to the target window procedure, bypassing the remaining procedures in the chain, the return value must be zero.
← →
Чапаев носками хакера (2006-08-26 23:31) [3]> Function OnKeyHook(code: ShortInt; wParam: Word; lParam:
> Longint): Longint stdcall;
НЕ ЧИТАЙТЕ АРХАНГЕЛЬСКОГО!
← →
SUN_ALF © (2006-08-26 23:34) [4]=))))
Оперативно же Вы... =))
приступаю к разбору написанного =)
← →
SUN_ALF © (2006-08-26 23:47) [5]Ketmar © (26.08.06 23:31) [1] :
=) Честно говоря, эта тематика у него хромает. Только на том, что написано в книге, у меня своего из этой области ничего не получилось. Почитал СДК, кое-чаво прошарил -- и уже хоть что-то с перехватом есть =)
Zeqfreed © (26.08.06 23:31) [2] :
Эххх... по-русски бы, а то так я на 30% теряю суть... Видать потому и результат такой, какой видим.
Чапаев носками хакера (26.08.06 23:31) [3] :
А кто такой Архангельский? =)
← →
Ketmar © (2006-08-26 23:50) [6]> [5] SUN_ALF © (26.08.06 23:47)
если б только эта... тут сию личность уже неоднократно обсуждали. %-)
а заграничный язык надо знать. иначе очень-очень грустно программировать. %-)
намекну, что переменные должны быть у всех процессов одни и те же. тут MMF спасёт, или модуль на асме. %-)
← →
Чапаев носками хакера (2006-08-26 23:54) [7]А, значит у знаменитого Флёнова пример хука тоже с Архангельского передран... Скучно, граждане. :`-(
Советую запомнить, что тип WParam -- Cardinal, а не Word.
← →
Zeqfreed © (2006-08-26 23:59) [8]> [7] Чапаев носками хакера (26.08.06 23:54)
> Советую запомнить, что тип WParam -- Cardinal, а не Word.
Тип wparam — WPARAM, а не Cardinal :) Хотя разница тут и не имеет никакого существенного значения.
← →
Ketmar © (2006-08-26 23:59) [9]> [7] Чапаев носками хакера (26.08.06 23:54)
что однофигственно, потому что код всё равно кривой. %-)
← →
SUN_ALF © (2006-08-27 00:03) [10]Ketmar © (26.08.06 23:50) [6] :
Если б я еще знал, что такое MMF... =)
Ассемблер -- ладно, кой-чаво могу, хотя тоже не специалист.
"переменные должны быть у всех процессов одни и те же" -- имеется в виду у всех процессов, работающих в системе?
← →
Zeqfreed © (2006-08-27 00:05) [11]> [5] SUN_ALF © (26.08.06 23:47)
> Эххх... по-русски бы, а то так я на 30% теряю суть... Видать
> потому и результат такой, какой видим.Если значение code меньше нуля, то процедура ловушки должна передать сообщение ф-ции CallNextHookEx без дальнейшей его обработки и вернуть значение, возвращенное CallNextHookEx.
Чтобы предотвратить передачу сообщения системой другим обработчикам в цепи ловушек или целевой оконной процедуре, возвращаемое значение должно быть неравным нулю. Чтобы разрешить системе передать сообщение целевой оконной процедуре пропуская оставшиеся обработчики в цепи ловушек, возвращаемое значение должно равняться нулю.
← →
Ketmar © (2006-08-27 00:05) [12]> [10] SUN_ALF © (27.08.06 00:03)
memory-mapped files.
> имеется в виду у всех процессов, работающих в системе?
угу. глянь на логику: KeyHook и handle должны быть одинаковыми во всех экземплярах DLL, нес па? это решается обычно при помощи MMF. или shared-секций в PE, которые дельфи создавать не умеет (отсюда и асм. или си. или ещё кто угодно, кто позволяет задавать секциям флаги руками).
← →
Чапаев носками хакера (2006-08-27 00:05) [13]> [9] Ketmar © (26.08.06 23:59)
Злой ты...
← →
Ketmar © (2006-08-27 00:06) [14]> [13] Чапаев носками хакера (27.08.06 00:05)
ну так что вижу, о том и пою...
← →
Zeqfreed © (2006-08-27 00:07) [15]> [10] SUN_ALF © (27.08.06 00:03)
> Если б я еще знал, что такое MMF... =)
MMF — Memory Mapped Files. См. CreateFileMapping, MapViewOfFile[Ex].
← →
SUN_ALF © (2006-08-27 00:10) [16]Гы, весело с ваами =))
По поводу Фленова: он просто обьясняет все вещи, даже самые сложные, на уровне детского сада. Соответственно, сие обьяснение покатит только для данного конкретного случая. И как результат, научившийся программить только по книгам Фленова юзер перейдя к чему-то подобному, но уже не такому, как было в книге, натыкается на грабли. Сиих граблей он бы не встретил, если автор дал "широкомасштабный" ответ по данному вопросу.
ИМХО, конечно... =)
← →
SUN_ALF © (2006-08-27 00:22) [17]Zeqfreed © (27.08.06 00:07) [15] :
Спасибо.
Ketmar © (27.08.06 00:05) [12] :
"угу. глянь на логику: KeyHook и handle должны быть одинаковыми во всех экземплярах DLL, нес па?"
Хм... а что значит "нес па?" ? =).
Экземпляры ДЛЛ? Она же вроде один только раз загружается в память...
И если ее раз 5-10 в течение одной минуты загрузить, то она последующие минут 10 не будет выгружаться в ожидании, что программка будет запускатсья еще ("отложенная выгрузка ДЛЛ" -- вроде так называется?).
← →
Ketmar © (2006-08-27 00:33) [18]> [17] SUN_ALF © (27.08.06 00:22)
system-wide хук грузит (или отображает, если правильнкая база; но в данном случае -- радостно грузит каждый раз, засоряя бедной машине мозги %-) DLL в АП каждого процесса. gdi32.dll на диске тоже один, но в памяти у каждого процесса свой. %-) так что натурально, у каждого процесса будет по экземпляру. а у каждого экземпляра -- по своей копии переменных.
← →
Ketmar © (2006-08-27 00:33) [19]"нес па" -- это "не так ли?". Стругацких надо читать. %-)
← →
SUN_ALF © (2006-08-27 02:53) [20]Ketmar © (27.08.06 00:33) [19] :
Ясно, спасибо =)
Надо подумать над всем этим...
← →
Германн © (2006-08-27 03:13) [21]
> SUN_ALF © (27.08.06 02:53) [20]
>
> Ketmar © (27.08.06 00:33) [19] :
> Ясно, спасибо =)
> Надо подумать над всем этим...
Над этим думать не надо! :-)
Думай лучше над Ketmar © (27.08.06 00:33) [18]!
← →
SUN_ALF © (2006-08-27 14:46) [22]Ладно... отставим MMF и загрузку ДЛЛ в память каждого процесса в сторонку. Попробуем поставить задачу проще: ловушка реагирует на нажатие клавиши, определяет указатель окна, в котором произошло событие, генерирует нажатие другой клавиши и отправляет сообщение окну по указателю. При этом остальные обработчики прерываний в очереди пропускаются.
Насколько я понимаю, тип ловушки WH_KEYBOARD здесь не подойдет, т.к. ей не передаются никакие укзатели. Значит, нужно что-то типа WH_GETMESSAGE, я прав? Если прав, где в получаемых параметрах и структуре хранится код нажатой клавиши, а то я так и не нашел =)
На листинге 3 мой шаблон ловушки.
----------------------------------------------------------
ЛИСТИНГ 3:
Function OnKeyHook(code: ShortInt; wParam: Word; lParam: Longint): Longint stdcall;
Begin
if code < 0 then
Result:= CallNextHookEx(KeyHook, code, wParam, lParam)
else
if code = HC_ACTION then
if TMsg(Pointer(lParam)^).message = WM_KEYDOWN then
begin
handle:= TMsg(Pointer(lParam)^).hwnd;
... { вот тут и не знаю, чего написать =) Можно ли обойтись функцией SendMessage ?? }
Result:= 0;
end;
End;
-----------------------------------------------------
← →
Ketmar © (2006-08-27 15:05) [23]так. начнём повторять сначала. а точнее, не начнём, потому что уже всё сказано. иди, и пока не перепишешь нормально DLL -- не возвращайся. %-)
далее: у окон нет "указателей", у них есть handles.
WH_KEYBOARD -- это всего лишь частный случай WH_GETMESSAGE (буквоедам: "да, я знаю, что земля не круглая" (ц)).
если так лениво писать нормальную DLL, можно использовать низкоуровневые хуки, пожерствовав работоспособностью в 9x и NT4.
← →
Ketmar © (2006-08-27 15:05) [24]а, да: за использоваение в хуках SendMessage() -- пожизненый эцих без гвоздей.
← →
SUN_ALF © (2006-08-27 15:18) [25]Ketmar © (27.08.06 15:05) [24] :
=)))
Ставлю вопрос раком (только в эцих с гвоздями не сажайте =) ): как написать нормальную ДЛЛ? А то я чего-то не понимаю, что вкладывается в слово "нормальную" в данном случае... =)
← →
Ketmar © (2006-08-27 15:27) [26]уже сказано. MMF. и базу поменять на что-то экзотическое. %-)
← →
Ketmar © (2006-08-27 15:28) [27]и -- нет. от меня кода не получишь. разве кто другой нарушит воспитательный процесс. %-)
← →
SUN_ALF © (2006-08-27 15:41) [28]Ketmar © (27.08.06 15:28) [27] :
=)
Ушел в поисках MMF...
Все еще раз спасибо, надеюсь, через нелею вернусь =)
← →
Юрий Зотов © (2006-08-27 17:28) [29]> SUN_ALF © (27.08.06 15:41) [28]
И замените тип wParam, ведь говорили уже. Иначе потом наловитесь глюков.
Насчет SendMessage. Хук шлет сообщение. И перехватывает его же. Снова шлет. И снова перехватывает. Что получится?
← →
SUN_ALF © (2006-08-31 15:39) [30]Юрий Зотов © (27.08.06 17:28) [29] :
пожизненный ицик с гвоздями =)))
← →
Romkin © (2006-08-31 16:00) [31]http://www.delphimaster.ru/articles/hooks/index.html
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.10.15;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.045 c