Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Перехват нажатий клавиш в системе. [D7, Win2k, WinXP]


Страницы:   1 2

SUN_ALF ©   (2006-08-26 23:25:00) 

Доброго времени суток, господа!
Писал "ловушку" для нажатий клавиш в системе. Тестовый вариант (полностью текст библиотеки вместе с процедурой установки ловушки на листинге 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;
-----------------------------------------------------


Romkin   (2006-08-31 16:00:00) [1]

http://www.delphimaster.ru/articles/hooks/index.html


SUN_ALF   (2006-08-31 15:39:00) [2]

Юрий Зотов ©   (27.08.06 17:28) [29] :
пожизненный ицик с гвоздями =)))


Юрий Зотов   (2006-08-27 17:28:00) [3]

> SUN_ALF ©   (27.08.06 15:41) [28]

И замените тип wParam, ведь говорили уже. Иначе потом наловитесь глюков.

Насчет SendMessage. Хук шлет сообщение. И перехватывает его же. Снова шлет. И снова перехватывает. Что получится?


SUN_ALF   (2006-08-27 15:41:00) [4]

Ketmar ©   (27.08.06 15:28) [27] :
=)
Ушел в поисках MMF...
Все еще раз спасибо, надеюсь, через нелею вернусь =)


Ketmar   (2006-08-27 15:28:00) [5]

и -- нет. от меня кода не получишь. разве кто другой нарушит воспитательный процесс. %-)


Ketmar   (2006-08-27 15:27:00) [6]

уже сказано. MMF. и базу поменять на что-то экзотическое. %-)


SUN_ALF   (2006-08-27 15:18:00) [7]

Ketmar ©   (27.08.06 15:05) [24] :
=)))
Ставлю вопрос раком (только в эцих с гвоздями не сажайте =) ): как написать нормальную ДЛЛ? А то я чего-то не понимаю, что вкладывается в слово "нормальную" в данном случае... =)


Ketmar   (2006-08-27 15:05:00) [8]

а, да: за использоваение в хуках SendMessage() -- пожизненый эцих без гвоздей.


Ketmar   (2006-08-27 15:05:00) [9]

так. начнём повторять сначала. а точнее, не начнём, потому что уже всё сказано. иди, и пока не перепишешь нормально DLL -- не возвращайся. %-)

далее: у окон нет "указателей", у них есть handles.

WH_KEYBOARD -- это всего лишь частный случай WH_GETMESSAGE (буквоедам: "да, я знаю, что земля не круглая" (ц)).

если так лениво писать нормальную DLL, можно использовать низкоуровневые хуки, пожерствовав работоспособностью в 9x и NT4.


SUN_ALF   (2006-08-27 14:46:00) [10]

Ладно... отставим 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;
-----------------------------------------------------


Германн   (2006-08-27 03:13:00) [11]


> 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 02:53:00) [12]

Ketmar ©   (27.08.06 00:33) [19] :
Ясно, спасибо =)
Надо подумать над всем этим...


Ketmar   (2006-08-27 00:33:00) [13]

"нес па" -- это "не так ли?". Стругацких надо читать. %-)


Ketmar   (2006-08-27 00:33:00) [14]

> [17] SUN_ALF ©   (27.08.06 00:22)
system-wide хук грузит (или отображает, если правильнкая база; но в данном случае -- радостно грузит каждый раз, засоряя бедной машине мозги %-) DLL в АП каждого процесса. gdi32.dll на диске тоже один, но в памяти у каждого процесса свой. %-) так что натурально, у каждого процесса будет по экземпляру. а у каждого экземпляра -- по своей копии переменных.


SUN_ALF   (2006-08-27 00:22:00) [15]

Zeqfreed ©   (27.08.06 00:07) [15] :
Спасибо.

Ketmar ©   (27.08.06 00:05) [12] :
"угу. глянь на логику: KeyHook и handle должны быть одинаковыми во всех экземплярах DLL, нес па?"
Хм... а что значит "нес па?" ? =).
Экземпляры ДЛЛ? Она же вроде один только раз загружается в память...
И если ее раз 5-10 в течение одной минуты загрузить, то она последующие минут 10 не будет выгружаться в ожидании, что программка будет запускатсья еще ("отложенная выгрузка ДЛЛ" -- вроде так называется?).


SUN_ALF   (2006-08-27 00:10:00) [16]

Гы, весело с ваами =))
По поводу Фленова: он просто обьясняет все вещи, даже самые сложные, на уровне детского сада. Соответственно, сие обьяснение покатит только для данного конкретного случая. И как результат, научившийся программить только по книгам Фленова юзер перейдя к чему-то подобному, но уже не такому, как было в книге, натыкается на грабли. Сиих граблей он бы не встретил, если автор дал "широкомасштабный" ответ по данному вопросу.
ИМХО, конечно... =)


Zeqfreed   (2006-08-27 00:07:00) [17]

> [10] SUN_ALF ©   (27.08.06 00:03)


> Если б я еще знал, что такое MMF... =)

MMF — Memory Mapped Files. См. CreateFileMapping, MapViewOfFile[Ex].


Ketmar   (2006-08-27 00:06:00) [18]

> [13] Чапаев носками хакера   (27.08.06 00:05)
ну так что вижу, о том и пою...


Чапаев носками хакера   (2006-08-27 00:05:00) [19]

> [9] Ketmar ©   (26.08.06 23:59)

Злой ты...


Ketmar   (2006-08-27 00:05:00) [20]

> [10] SUN_ALF ©   (27.08.06 00:03)
memory-mapped files.

> имеется в виду у всех процессов, работающих в системе?
угу. глянь на логику: KeyHook и handle должны быть одинаковыми во всех экземплярах DLL, нес па? это решается обычно при помощи MMF. или shared-секций в PE, которые дельфи создавать не умеет (отсюда и асм. или си. или ещё кто угодно, кто позволяет задавать секциям флаги руками).


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо