Форум: "WinAPI";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
ВнизHooks Найти похожие ветки
← →
VVV-First (2005-04-26 16:14) [0]Может кто подскажет мен в следующем вопросе.
Устнанавливаю глобальный хук на клаву. Регистрирую в системе свое событие и затем в функции фильтре (в DLL )при нажатии определенной клавиши передаю это сообщение своему Host- приложению средствами SendMessage(). Если открыть например блокнот то все просто отлично , все нажатые клавиши в блокноте, отлавливаются моим хуком и соответственно передаются в мое Host-приложение. Но вот если открыть например Word то после нажатия нескольких клавишь Word начинает тормозить,а потом и вовсе зависает. Может кто подскажет почему?
Может надо использовать не SendMessage() а PostMessage() ?
← →
mgcr © (2005-04-26 16:18) [1]
> Может кто подскажет почему?
Потому что хук кривой.
← →
VVV-First (2005-04-26 16:24) [2]
> Потому что хук кривой.
Серьезная такая подсказка:))))))))) Вот это спасибо:)))))
Все прям прояснилось:)))))))))))
← →
ANB © (2005-04-26 16:56) [3]
mgcr © (26.04.05 16:18) [1]
- прав. Хук у тебя и правду кривой. Хочешь по теме - выложи исходник. Тока сначала убери stdcall в procedure DLLEntryPoint(dwReason: Integer);
← →
VVV-First (2005-04-26 16:58) [4]
> Тока сначала убери stdcall в
хмммм а я читал , что это не только не повредит , а еще и поможет , но всерано пасибо , вечером попробую
← →
ANB © (2005-04-26 17:18) [5]МОДЕРАТОРЫ !!!! УБЕРИТЕ СТАТЬЮ ПРО ХУКИ ИЛИ ИСПРАВЬТЕ ПРИМЕР !!! ЭТО УЖЕ ПЯТЫЙ ЧЕЛОВЕК (ВКЛЮЧАЯ МЕНЯ) НАРЫВАЕТСЯ.
> что это не только не повредит , а еще и поможет
- это где ты прочитал ?
← →
alpet © (2005-04-26 17:54) [6]Вопрос: заменять DLLEntryPoint с помощью секций intialization/finallization вообще можно ?
← →
ANB © (2005-04-26 18:04) [7]Завтра выложу исходник работающей DLL. Пока.
← →
mgcr © (2005-04-26 18:16) [8]ANB © (26.04.05 17:18) [5]
А голова человеку на что дана ?
← →
Eraser © (2005-04-26 20:20) [9]VVV-First
Если лень разбираться в теории, то поищи в нете ещё один пример, благо их сотни...
← →
ANB © (2005-04-27 09:09) [10]Это пример хука WH_GETMESSAGE. Правильный и полностью работающий. Обмен с хост-приложением происходит при помощи WM_COPYDATA + Метка своим сообщением. Оказался оптимальным вариантом.
> mgcr © (26.04.05 18:16) [8]
> ANB © (26.04.05 17:18) [5]
>
> А голова человеку на что дана ?
- мне помогли в этом форуме, почему не помочь другим ?
А проблема в неправильном определении DLLEntryPoint и к теории хуков никакого отношения не имеет. Я сам перелопатил всего Рихтера, а с первого раза не написал.
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_LBUTTONUP)
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.
← →
Digitman © (2005-04-27 09:33) [11]
> alpet © (26.04.05 17:54) [6]
> Вопрос: заменять DLLEntryPoint с помощью секций intialization/finallization
> вообще можно ?
а зачем ?
в чем глубокий смысл сего извращения ?
← →
alpet © (2005-04-28 11:11) [12]Digitman © (27.04.05 09:33) [11]
1. Вечный вопрос.
2. Мультиплатформность разве что... впрочем она обеспечивается назначением обработчика DllProc(Ex).
Собственно ответ - нельзя. Другое дело что юниты подключаемые к DLL вполне сносно отрабатывают секцию initialization по уведомлению DLL_PROCESS_ATTACH, и finalization по уведомлению DLL_PROCESS_DETACH.
← →
VVV-First (2005-04-28 12:41) [13]
> ANB © (27.04.05 09:09) [10]
а твоя библиотечка так мою напоминает, но всеравно , дома сравню что не так
А прочитал я статью на сайте DELPHI WORLD
← →
ANB © (2005-04-28 16:33) [14]
> а твоя библиотечка так мою напоминает
- с одного места драли :)))
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.038 c