Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.039 c
15-1158757271
DelphiLexx
2006-09-20 17:01
2006.10.15
Структура будущей проги


15-1158931308
Megabyte
2006-09-22 17:21
2006.10.15
Firebird 2.0 и IB_Expert 2.5.0.22


2-1159533557
KyRo
2006-09-29 16:39
2006.10.15
Открывается ли файл


2-1158667148
[PSIH]
2006-09-19 15:59
2006.10.15
Insufficient memory for this operation


2-1159682879
одиндватри
2006-10-01 10:07
2006.10.15
операторные скобки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский