Форум: "WinAPI";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];
ВнизSetWindowsHookEx и невнимательность ? Найти похожие ветки
← →
Sphinx © (2005-09-20 21:15) [0]Есть код установки хука и снятия
//------------------------------------------------------------------------------
// функция установки ловушки
//------------------------------------------------------------------------------
function SetWndProcHook: HResult; stdcall;
begin
WndProcHook := SetWindowsHookEx(WH_CALLWNDPROC {WH_KEYBOARD}, @HookWindowProc, HInstance, 0);
if WndProcHook = 0 then
SetWndProcHook := E_FAIL
else
SetWndProcHook := S_OK;
end;
//------------------------------------------------------------------------------
// функция снятия ловушки
//------------------------------------------------------------------------------
function UnSetWndProcHook: HResult; stdcall;
begin
if UnhookWindowsHookEx(WndProcHook) then
UnSetWndProcHook := S_OK
else
UnSetWndProcHook := E_FAIL;
end;
Есть callback функция//------------------------------------------------------------------------------
// функция обработки сообщений ловушки
//------------------------------------------------------------------------------
function HookWindowProc(nCode: Longint; wParam, lParam: Longint): Longint; stdcall;
var
pMsgStruct : PCWPStruct;
begin
HookWindowProc := CallNextHookEx(WndProcHook, nCode, wParam, lParam);
end;
вот так все работает без проблем.
Но стоит только повесить какую-либо обработку в функцию, например://------------------------------------------------------------------------------
// функция обработки сообщений ловушки
//------------------------------------------------------------------------------
function HookWindowProc(nCode: Longint; wParam, lParam: Longint): Longint; stdcall;
var
pMsgStruct : PCWPStruct;
begin
HookWindowProc := CallNextHookEx(WndProcHook, nCode, wParam, lParam);
if nCode = HC_ACTION then
begin
pMsgStruct := Pointer(lParam);
if pMsgStruct^.hwnd = AppWindowHandle then
begin
case pMsgStruct^.message of
WM_KEYDOWN : begin
// MessageBox(0, "KeyDown", "Debug", mb_ok);
end;
end;
end;
end;
end;
и система падает. (выскакивают AV explorer.exe и всех остальных процессов с обращением к нулевой памяти)
Если выставить ловушку только на клавиатуру - то таких проблем нет, все корректно обрабатывается.
Хук естественно выполняется в dll. Такое ощущение, что какую-то мелочь пропустил по невнимательности (с хуками работаю в первый раз).
Суть задачи - следить за клавиатурой и мушью в пределах одного окна (ставить хук на клаву и мышь отдельно не хочется, потому, что не понял как в таком случае отлавливать события нажатия кнопки мыши).
← →
ANB © (2005-09-20 21:48) [1]
> MessageBox(0, "KeyDown", "Debug", mb_ok);
- вот это ты зря. Совсем зря. Нет фильтра на сообщения (реагируешь на движения мыши даже в своем приложении).
> AppWindowHandle
- откуда берешь это значение ?
Короче, вот рабочая хуковая DLL. Приладь там, что тебе нужно.
library Recorder;
uses Windows, Messages, SysUtils;
const
MMFName : PChar = "Recorder_MMF"; // имя объекта файлового отображения
{структура, поля которой будут отображены в файл подкачки}
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
SysHook : HWND; // дескриптор установленной ловушки
MainRecorderWnd : hWnd; // дескриптор окна рекордера
MainRecorderProcessID : THandle; // ID процесса рекордера
end;
var
MMFHandle : THandle;
WM_Recorder_HOOK : Cardinal;
GlobalData : PGlobalDLLData;
function RecordCallBackProc(Code : Integer;
wParam : WPARAM;
lParam : LPARAM) : LRESULT; stdcall;
var hCallWnd : HWND;
ProcessID : THandle;
EventMsg : TMsg;
SysHook : THandle;
MsgData : TCOPYDATASTRUCT;
begin
Result := 0;
SysHook := 0;
try
// Прочитаем SysHook из разделяемой памяти
SysHook := GlobalData^.SysHook;
// Проверим коды
if (Code <> HC_ACTION) then Exit;
if (wParam <> PM_REMOVE) then Exit;
EventMsg := TMsg(Pointer(lParam)^);
hCallWnd := EventMsg.hwnd;
// Выкинем лишние сообщения
if (
(EventMsg.message = WM_KEYDOWN)
or (EventMsg.message = WM_SYSKEYDOWN)
or (EventMsg.message = WM_COMMAND)
or (EventMsg.message = WM_LBUTTONDOWN)
or (EventMsg.message = WM_RBUTTONUP)
or (EventMsg.message = WM_MBUTTONUP)
) then begin
// Проверим, что события не нашего приложения
GetWindowThreadProcessId(hCallWnd, ProcessID);
if (ProcessID = GlobalData^.MainRecorderProcessID) then Exit;
// Передадим инфу о событии в рекордер
MsgData.dwData := WM_Recorder_HOOK;
MsgData.cbData := SizeOf(EventMsg);
MsgData.lpData := @EventMsg;
SendMessage(
GlobalData^.MainRecorderWnd
,WM_COPYDATA
,hCallWnd
,Integer(@MsgData));
end;
finally
CallNextHookEx(SysHook, Code, wParam, lParam);
end;
end;
{Процедура установки HOOK-а}
function Set_Hook(hMainWnd : HWND; MainProcessID : THandle) : Boolean; export; stdcall;
begin
// Устанавливаю HOOK
Result := False;
// Поставим хук
GlobalData^.SysHook := SetWindowsHookEx(WH_GETMESSAGE, @RecordCallBackProc,
HInstance, 0);
GlobalData^.MainRecorderWnd := hMainWnd;
GlobalData^.MainRecorderProcessID := MainProcessID;
if (GlobalData^.SysHook = 0)
then
MessageBox(0, "Ошибка : не удалось установить хук WH_GETMESSAGE !",
"Сообщение от Recorder.dll", 0)
else Result := True;
end;
{Процедура снятия HOOK-а}
function Reset_Hook() : Boolean; export; stdcall;
begin
// Удаляем функцию-фильтр
Result := False;
// Снимем хук
if (not UnhookWindowsHookEx(GlobalData^.SysHook))
then MessageBox(0, "Ошибка : не удалось снять хук WH_GETMESSAGE !",
"Сообщение от Recorder.dll", 0)
else Result := True;
end;
procedure OpenGlobalData();
var sMsg : String;
begin
// Зарегистрим наше сообщение
WM_Recorder_HOOK := RegisterWindowMessage("WM_Recorder_HOOK");
// Подключим MMF
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0,
SizeOf(TGlobalDLLData), MMFName);
if MMFHandle = 0 then begin
sMsg := "Ошибка : не удалось создать MMF <" + MMFName + ">";
MessageBox(0, PChar(sMsg), "Сообщение от Recorder.dll", 0);
Exit;
end;
GlobalData := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0,
SizeOf(TGlobalDLLData));
if (GlobalData = nil) then begin
sMsg := "Ошибка : не удалось отобразить MMF <" + MMFName + ">";
MessageBox(0, PChar(sMsg), "Сообщение от Recorder.dll", 0);
end;
end;
procedure CloseGlobalData();
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
procedure DLLEntryPoint(dwReason: Integer);
begin
case dwReason of
DLL_PROCESS_ATTACH : OpenGlobalData();
DLL_PROCESS_DETACH : CloseGlobalData();
end;
end;
exports Set_Hook, Reset_Hook;
begin
{назначим поцедуру переменной DLLProc}
DLLProc := @DLLEntryPoint;
{вызываем назначенную процедуру для отражения факта присоединения данной
библиотеки к процессу}
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
← →
Sphinx © (2005-09-20 22:06) [2]2 ANB ©
Рад бы не реагировать - но я просто проверял этим работоспособность кода...
А мне в ответ систему валило :(
> > AppWindowHandle
> - откуда берешь это значение ?
при инициализации dll вводится THandle окна, события которого и надо отслеживать (кроме отслеживание событий библиотека еще некоторые функции с окном выполняет).
Собственно этот хэндл и хранится вAppWindowHandle
Эту (или подобную dll я уже скачал из соответствующей статьи тут), но тогда придется многое у себя переделать, если в моем коде ошибка в самой задаче установки хука - тогда ни куда уж не денешься, а если я всего-лишь что-то пропустил, то может можно просто исправить, не меняя сильно структуру библиотеки.
← →
ANB © (2005-09-20 22:17) [3]
> Собственно этот хэндл и хранится в AppWindowHandle
- а в копиях - теряется. Внедряется только код, все переменные становятся неопределенными. Думаешь мне очень хотелось MMF использовать ?
← →
Sphinx © (2005-09-20 22:26) [4]2 ANB ©
Тааааак...кажется дошло...
Завтра проверю...
Но если это глобальная переменная для библиотеки, и в упрощенном виде:procedure Init(iHandle: THandle);
begin
AppWindowHandle := iHandle
end;
Все равно значение будет потеряно ???
← →
ANB © (2005-09-20 22:51) [5]Есно. Почитай про процесс внедрения. Об этом даже в статье на этом сайте говорится. Там есть только одна ошибка в примере. А так - все грамотно разжевано. Я свой код из этого примера лепил.
← →
Sphinx © (2005-09-21 09:47) [6]Ладно, с этим еще поразбираюсь...
Настораживает следующее. Внимательно просмотрел пример и вот, что нашел:function KeyboardProc(code : integer; wParam : word; lParam : longint) : longint; stdcall;
В то время как и в Windows SDK из Delphi7 и в MSDN January2005LRESULT CALLBACK CallWndProc(
int nCode,
WPARAM wParam,
LPARAM lParam
);
Windows.pasWPARAM = LongInt;
у меня написаноfunction HookWindowProc(nCode: Longint; wParam, lParam: Longint): Longint; stdcall;
и собственно любая попытка получить данные приводит к падению системы...
Так каким должен быть второй параметрWord
илиLongint(WPARAM)
???
← →
Sphinx © (2005-09-21 09:49) [7]Сорри...для одинаковости привожу обратный вызов для клавиатуры:
LRESULT CALLBACK KeyboardProc(
int code,
WPARAM wParam,
LPARAM lParam
);
все равно та же фигня с WPARAM
← →
ANB © (2005-09-21 11:14) [8]
> word
- замени на DWord. А ты это в чьем примере нашел ? Неужто у меня ?
Возьми статью, а для примера возьми мою DLL. Если очень надо - могу выложить код ставящего хук и принимающего сообщения модуля. Но там много лишнего.
← →
Sphinx © (2005-09-21 11:28) [9]2 ANB ©
в примере к статье...
http://delphimaster.ru/articles/hooks/index.html
кстати об этом же написано и в
http://delphimaster.net/view/4-1121277980/ (9й пост)
интересно, что там именно Word а не DWord :\
сейчас нету под рукой Делфи...смогу проверить только вечером.
Огромное спасибо...если не получится - просто откопипастю какой-нибудь пример и подгоню под свои нужды...
← →
ANB © (2005-09-21 14:53) [10]
> Sphinx © (21.09.05 11:28) [9]
- ну так и копипасти мой. Я для чего его выкладывал ?
← →
-=S..S=- (2005-09-27 11:14) [11]У меня была аналогичная проблема ... ANB © (20.09.05 22:17) [3] абсолютно прав ... надо использовать глобал мемори ... иначе никак ... писал я как то длл которая и на клаву и на мышу реагировала ... все ок было .. токо хз когда я до неё доберусь :) ... если очень надо то в понедельник скорее всего скину ... да и впринципе тебе уже всё обяснили .. так что часика два посиди .. сам напишешь :)
← →
Sphinx © (2005-09-27 14:53) [12]Я уже сделал...
Огромное спасибо - все норм реагирует :)
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.11.27;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.014 c