Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Hook на клавиатуру, не передает клавишу :( 
:(
    Опции темы
Domoffou
Дата 13.11.2008, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 22.6.2008
Где: Северная Венеция

Репутация: нет
Всего: нет



Здравствуйте.
Написал хук на клавиатуру (в dll), который прекрасно работал (месяца 3) до тех пор,
пока я не сел поиграть в Diablo II LOD.
Претензий к хуку (как к перехватчику) нет вообще - все прекрасно ловится.
Вопрос только в том, что в Diablo II LOD во время работы хука перестают работать обычные клавиши.
К примеру, работают клавиши Escape, Enter, F1 - F12, да и вообще все системные клавиши, кроме букв.
Т.е. в лог они записываются, а сама игра на них никак не реагирует.
Что самое интересное, если нажать клавишу Enter (для того, чтобы написать в общем чате), то все буквы прекрасно печатаются.
Т.е. обычные буквы в логе появляются, при печатании сообщения в игре тоже, а если жмем, к примеру, B - чтобы открыть рюкзак, то ничего не происходит (будет работать только после выгрузки хука).
Что примечательно, хук адекватно работать с Unreal Tournament 2004.

Хотел бы поинтересоваться, в чем м.б. проблема, и вообще решается ли она?

Код

library myhook;

uses
  Windows,
  Messages;

  type
  PGlobalDLLData = ^TGlobalDLLData;
  TGlobalDLLData = packed record
    MainHandle: HWND;
  end;

  KBDLLHOOKSTRUCT = record
    vkCode: DWORD;
    scanCode: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo:Pointer;
  end;
  PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;


var
  WM_MYSUPERMESSAGE: Cardinal;
  SysHook: HWND;

  //глобальные переменные
  GlobalData: PGlobalDLLData;
  MMFHandle: THandle;

function SysHook1(ncode: integer; WParam: Word; lParam: Longint): Longint; stdcall;
var
  p: KBDLLHOOKSTRUCT;
begin

if ncode < 0 then
  begin
    Result:= CallNextHookEx(SysHook, nCode, wParam, lParam);
    Exit;
  end;

 if (wparam = WM_KEYDOWN) or (wparam = WM_SYSKEYDOWN) then
    begin
      p := PKBDLLHOOKSTRUCT(lParam)^;
      PostMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 
    end;

Result := CallNextHookEx(SysHook, nCode, wParam, lParam);
end;


procedure SetHook();stdCall; export;
begin
    SysHook:= SetWindowsHookEx(13, @SysHook1, hInstance, 0);
end;

procedure DelHook;stdCall; export;
begin
  UnmapViewOfFile(GlobalData);
  CloseHandle(MMFHandle);

  if SysHook <> 0 then
    UnhookWindowsHookEx(SysHook);
  SysHook:=0;
end;


exports
  SetHook,
  DelHook;

begin
WM_MYSUPERMESSAGE := RegisterWindowMessage('WM_MYSUPERMESSAGE');

MMFHandle:= CreateFileMapping(MAXDWORD , nil, PAGE_READONLY, 0, SizeOf(TGlobalDLLData), GlobalName);
  GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_READ, 0, 0, SizeOf(TGlobalDLLData));
end.


Кстати, если строку
Код

PostMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 

заменить на
Код

SendMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 

то Diablo работает корректно  smile 


PM MAIL ICQ   Вверх
THandle
Дата 13.11.2008, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3638
Регистрация: 31.7.2007
Где: Moscow

Репутация: 7
Всего: 372



Цитата

Кстати, если строку
Код

PostMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 

заменить на
Код

SendMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 

то Diablo работает корректно  smile


У меня нет никаких там Diabloв, но видимо в этом и есть дело, значит. Ведь PostMessage кладет сообщение в очередь... Пока оно обработается много может времени пройти...
PM   Вверх
Domoffou
Дата 13.11.2008, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 22.6.2008
Где: Северная Венеция

Репутация: нет
Всего: нет



Цитата(THandle @ 13.11.2008,  19:28)
Цитата

Кстати, если строку
Код

PostMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 

заменить на
Код

SendMessage(GlobalData^.MainHandle, WM_MYSUPERMESSAGE, p.vkCode, p.scanCode); 

то Diablo работает корректно  smile


У меня нет никаких там Diabloв, но видимо в этом и есть дело, значит. Ведь PostMessage кладет сообщение в очередь... Пока оно обработается много может времени пройти...

В этом то и вопрос, ведь, если не ошибаюсь, во время перехвата клавиши происходит следующее:
1. перехват клавиши.
2. отправляем через postmessage сообщение для моей программы
3. не дожидаясь пока программа его обработает, сразу же возвращаем клавишу дальше (к следующему хуку).

PostMessage кладет сообщение в очередь не дожидаясь ответа и сразу переходит к передаче введенной клавиши далее к следующему хуку (или к ОС).
Следовательно, сообщение PostMessage не должно зависеть от CallNextHook, ноборот, везде советуют использовать именно такую форму отправки сообщений (т.к. SendMessage - это отправка сообщения, как я понимаю, с ожиданием ответа).

Это сообщение отредактировал(а) Domoffou - 13.11.2008, 21:44
PM MAIL ICQ   Вверх
dumb
Дата 14.11.2008, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 7
Всего: 158



Domoffou, для низко-уровневых хуков DLL не нужна - вызов хук-процедуры происходит в контексте потока, установившего хук. соответственно отпадает надобность в меж-процессном взаимодействии(IPC) в виде всех этих MMF/Send/PostMessage.

поиск по форуму по слову WH_KEYBOARD_LL.
PM MAIL   Вверх
Domoffou
Дата 14.11.2008, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 22.6.2008
Где: Северная Венеция

Репутация: нет
Всего: нет



ок, я понял, но в данный момент у меня проходит довольно большая проверка на каждую клавишу, поэтому если я реализую это в конкретном приложении, в котором помимо обработки еще штуки 4 таймера, я рискую подвиснуть вообще... как мне обрабатывать клавишу, ну не в потоке же?
А если использовать хук то, теоретически, он делает PostMessage и сразу продолжает работать.
PM MAIL ICQ   Вверх
dumb
Дата 14.11.2008, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 7
Всего: 158



от того, что ты разместил код в DLL ничего не меняется.
после установки LL-хука, при нажатии клавиши система переключает контекст на поток, установивший хук(а это главный поток твоего приложения), и в этом контексте вызывает код хук-процедуры. таким образом ты можешь спокойно пользоваться всеми своими данными как обычно.
оглядываться стоит только на время выполнения: не стоит делать всякие Sleep/ProcessMessages и другие блокирующие вызовы.
если необходимо отложить обработку, то надо просто записать все данные из хука в обычную очередь(TList там какой-нибудь) - никаких ограничений на кол-во данных, как в случае с PostMessage.
подвиснуть ты не рискуешь - при превышении опр.времени система просто отдаст "нажатие" дальше по цепочке.

цитировать не стал, так как ничего ты особо не понял, и практически все, что написал, смысла не имеет(мягко говоря).
PM MAIL   Вверх
Domoffou
Дата 14.11.2008, 18:27 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 22.6.2008
Где: Северная Венеция

Репутация: нет
Всего: нет



Цитата(dumb @ 14.11.2008,  17:01)
ты особо не понял, и практически все, что написал, смысла не имеет(мягко говоря).

Я, конечно, понимаю, что вышенаписанный мною код содержит ошибки, причем при реализации, но прошу не показывать, что твои знания выше моих, я и так без этого догадываюсь, раз я спрашиваю а ты отвечаешь.

Теперь я догадался, что мои попытки использовать в хуке PostMessage бессмысленны, т.к. использовать данный хук можно и вовсе внутри приложения... да и при зависании основного exe (или при длительном выполнении какой-либо операции), хук попросту зависает, не возвращая системе ничего... следовательно от этого все тормоза при перезагруженной системе.

Но реально сейчас я не могу встроить хук в само приложение, т.к. оно уже весит около мегабайта и в нем и так содержатся куча других функций, ряд из которых нужно выполнять незамедлительно. К примеру, во время выполнения очередной операции придет клавиша, которую необходимо будет обработать, а приложение в недосягаемости. Соответственно, необходимость TStringList отпадает.

Пришел к выводу, что необходимо в таком случае писать доп. ехе, в которой уже будет стоять низкоуровневый хук на клавиатуру (и др. хуки), который уже посредством PostMessage будет общаться с основной программой. Только в данном случае при отправке PostMessage приложение-хук зависать не будет в случае недосягаемости основного приложения-обработчика. Конечно, два активных ехе для одной программы - черезчур, но если выхода другого нет, то...

Поправьте, если я не прав?

Это сообщение отредактировал(а) Domoffou - 14.11.2008, 18:29
PM MAIL ICQ   Вверх
MetalFan
Дата 14.11.2008, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



может ставить LL хук в доп.потоке основного приложения? тогда и осн.поток виснуть не будет, и хук будет нормально работать...
только надо учесть примечания в библии (aka MSDN):
Цитата(MSDN)
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop. 


Цитата(Domoffou @  14.11.2008,  18:27 Найти цитируемый пост)
да и при зависании основного exe (или при длительном выполнении какой-либо операции), хук попросту зависает, не возвращая системе ничего... 

тут ты наверное не прав, ибо библийа гласит:
Цитата(MSDN)
The hook procedure should process a message in less time than the data entry specified in the LowLevelHooksTimeout value in the following registry key: 
HKEY_CURRENT_USER\Control Panel\Desktop

The value is in milliseconds. If the hook procedure does not return during this interval, the system will pass the message to the next hook.





--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Domoffou
Дата 14.11.2008, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 60
Регистрация: 22.6.2008
Где: Северная Венеция

Репутация: нет
Всего: нет



Цитата(MetalFan @  14.11.2008,  19:29 Найти цитируемый пост)
может ставить LL хук в доп.потоке основного приложения? тогда и осн.поток виснуть не будет, и хук будет нормально работать...
только надо учесть примечания в библии (aka MSDN):

Интересная идейка... правда, честно говоря, не понимаю как реализовать установку хуков в отдельном потоке... м.б. установка хука должна производиться в основном,, а обработка - в отдельном потоке?
Проблема в том, что у меня еще есть WH_Mouse_LL и WH_CBT :(
а их, конечно, в идеале запихать вместе.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1490 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.