Вниз
Скачать: CL | DM;

Перехват нажатий клавиш в системе.   Найти похожие ветки 

← →
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 вся ветка

Скачать: CL | DM;



Память: 0.53 MB
Время: 0.028 c
15-1158757874
Cyrax
2006-09-20 17:11
2006.10.15
Языковая панель в Windows XP


3-1155220269
.ruslan
2006-08-10 18:31
2006.10.15
Изменить цвет помеченых строк в DBGridEh


15-1158872352
Eraser
2006-09-22 00:59
2006.10.15
Просьба протестировать сайт


11-1120242557
Владимир Кладов
2005-07-01 22:29
2006.10.15
Zoomer3


15-1157982846
Desdechado
2006-09-11 17:54
2006.10.15
Смайлики в Миранде




   Наверх