![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Перехват нажатий клавиш в системе. [D7, Win2k, WinXP]
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, которые дельфи создавать не умеет (отсюда и асм. или си. или ещё кто угодно, кто позволяет задавать секциям флаги руками).