Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
Const69
Зарегистрирован: 27.10.2005 Сообщения: 3
|
Добавлено: Чт Ноя 10 2005 19:31 Заголовок сообщения: Глюки в глобальном хуке (p.s. FAQи смотрел, не помогает) |
|
|
Сделал всё по-писаному -- написал DLL с хуками от клавы и мыши, с общей областью, посылкой сообщений главному окну и пр.
Работает замечательно. Всё перехватывает. Выключаю хуки, включаю, хоть сто раз, сбоев нет.
Глюки начинаются, когда я, при включенном хуке, раскрываю папку, которая лежит на desktop'е. Потом закрываю. Ничего больше.
Так вот, когда с первого раза, когда со второго. но глючить начинает обязательно.
Внешне это выглядит так: не активируется ни одна иконка на десктопе, не вызывается меню СТАРТ, десктоп не перерисовывается, а потом и вообще всё с десктопа исчезает, кроме фоновой картинки.
Те проги, что были запущены, работают. Единственно, что можно сделать -- нажать ctrl+alt+del и перегрузиться.
Что за нафиг? Кто-нибудь с таким сталкивался?
Кроме того. В callback-функциях хука (обработка событий в DLL), я должен возвращать результат.
Допустим, я ничего не хочу блокировать. Т.е. не должен возвращать 1. Как должна выглядеть моя обработка?
В разных источниках я видел разные варианты:
function KeybdHookProc (aCode, aWParam, aLParam: longint): longint; stdcall;
1) if ( aCode < 0 ) then begin
CallNextHookEx (...);
Result := 0;
end else begin
PostMessage (...); // моя обработка
Result := CallNextHookEx (...);
end;
2) if ( aCode < 0 ) then begin
Result := CallNextHookEx (...);
end else begin
PostMessage (...); // моя обработка
CallNextHookEx (...);
Result := 0;
end;
3) if ( aCode >= 0 ) then
PostMessage (...); // моя обработка
Result := CallNextHookEx (...);
Глючит при любом варианте.
И ещё. При создании хука, нужно задавать тип хука. По справке всё просто -- WH_KEYBOARD и WH_MOUSE.
Но в одном из примеров был такой вариант:
if ( integer(GetVersion) > 0 ) then begin // NT, 2000 ..
whK := 13; // WH_KEYBOARD_LL
whM := 14; //
end else begin // 95, 3.1 ...
whK := WH_KEYBOARD;
whM := WH_MOUSE;
end;
hKeybdHook := SetWindowsHookEx (whK, KeybdHookProc, hInstance, 0);
hMouseHook := SetWindowsHookEx (whM, MouseHookProc, hInstance, 0);
И как это понимать? У меня в XP всё прекрасно работает и с WH_KEYBOARD / WH_MOUSE.
Буду благодарен за любую помощь. |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
tinimi
Зарегистрирован: 27.03.2005 Сообщения: 90 Откуда: Win32
|
Добавлено: Вс Ноя 13 2005 11:57 Заголовок сообщения: |
|
|
WH_KEYBOARD_LL, WH_MOUSE_LL - ето низкоуровневый хук, он тебе не нужен.
Ты не кричи "глючит", а кинь свой кусок кода, ВЕСЬ!
Я в свое время такое делал и все работало.
А еще почитай чего нить по Win32API. Не просто справочник, а учебник. _________________ [ TiNiMi ] |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
Const69
Зарегистрирован: 27.10.2005 Сообщения: 3
|
Добавлено: Пн Ноя 14 2005 12:03 Заголовок сообщения: |
|
|
вот DLL (оставил только клаву):
Код: |
library hook_KM;
uses
Windows, Messages;
type
PHookData = ^THookData;
THookData =
record
hKeybdHook{, // хэндлы ловушек
hMouseHook}: HHook; //
hTargetWnd: HWnd; // хэндл окна-приёмника событий
end;
var
Mapped: boolean; //
EntryErr: longint;
DataP: PHookData;
hMMF: THandle; // хэндл мап-файла
WM_KeybdHook{, // сообщения о событиях
WM_MouseHook}: DWord; //
function KeybdHookProc (aCode, aWParam, aLParam: longint): longint; stdcall;
begin
if ( DataP = nil ) then begin
Result := CallNextHookEx (0, aCode, aWParam, aLParam);
end else begin
if ( aCode = HC_ACTION ) then
PostMessage (DataP^.hTargetWnd, WM_KeybdHook, aWParam, aLParam);
Result := CallNextHookEx (DataP^.hKeybdHook, aCode, aWParam, aLParam);
end;
end;
{
function MouseHookProc (aCode, aWParam, aLParam: longint): longint; stdcall;
begin
if ( DataP = nil ) then begin
Result := CallNextHookEx (0, aCode, aWParam, aLParam);
end else begin
if ( aCode = HC_ACTION ) then
PostMessage (DataP^.hTargetWnd, WM_MouseHook, aWParam, aLParam);
Result := CallNextHookEx (DataP^.hMouseHook, aCode, aWParam, aLParam);
end;
end;
}
// возврат 0 - всё нормально
function SetHook (anOn: boolean; aTargetWnd: HWnd): longint; export; stdcall;
begin
Result := EntryErr; if ( DataP = nil ) then Exit;
Result := 0;
with DataP^ do
if anOn then begin
hTargetWnd := aTargetWnd;
hKeybdHook := SetWindowsHookEx (WH_KEYBOARD, KeybdHookProc, hInstance, 0);
if (hKeybdHook = 0) then Result := GetLastError;
// hMouseHook := SetWindowsHookEx (WH_MOUSE, MouseHookProc, hInstance, 0);
// if (hMouseHook = 0) then Result := GetLastError;
end else begin
hTargetWnd := INVALID_HANDLE_VALUE;
if not UnHookWindowsHookEx (hKeybdHook) then Result := GetLastError; hKeybdHook := 0;
// if not UnHookWindowsHookEx (hMouseHook) then Result := GetLastError; hMouseHook := 0;
end;
end;
procedure DLLEntryPoint (aCode: DWord); stdcall;
begin
case aCode of
DLL_PROCESS_ATTACH:
begin
if Mapped then Exit; Mapped := True;
EntryErr := 0;
WM_KeybdHook := WM_NULL;
// WM_MouseHook := WM_NULL;
hMMF := 0;
DataP := nil;
//---------------
WM_KeybdHook := RegisterWindowMessage ('WM_KEYBD_HOOK');
EntryErr := GetLastError;
if ( WM_KeybdHook = 0 ) then Exit;
// WM_MouseHook := RegisterWindowMessage ('WM_MOUSE_HOOK');
// EntryErr := GetLastError;
// if ( WM_MouseHook = 0 ) then Exit;
hMMF := CreateFileMapping (INVALID_HANDLE_VALUE,
nil,
PAGE_READWRITE,
0,
SizeOf(THookData),
'hook_KM_Area');
EntryErr := GetLastError;
if ( hMMF = 0 ) then Exit;
DataP := MapViewOfFile (hMMF,
FILE_MAP_ALL_ACCESS,
0,
0,
SizeOf(THookData));
EntryErr := GetLastError;
if ( DataP = nil ) then Exit;
EntryErr := 0;
end;
DLL_PROCESS_DETACH:
begin
Mapped := False;
UnmapViewOfFile (DataP); DataP := nil;
CloseHandle (hMMF); hMMF := 0;
EntryErr := -1;
end;
end;
end;
exports
SetHook;
begin
Mapped := False;
DLLProc := @DLLEntryPoint;
DLLEntryPoint (DLL_PROCESS_ATTACH);
end.
|
и форма:
Код: |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TSetHookProc = function (anOn: boolean; aTargetWnd: HWnd): longint; stdcall;
THook = class (TWinControl)
private
_FName: string;
_WM_KeybdHook,
_WM_MouseHook: DWord;
_DLL: THandle;
_SetProc: TSetHookProc;
_OnHook: TNotifyEvent;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure WndProc (var aMsg: TMessage); override;
public
LastErr: longint;
constructor Create (anOwner: TComponent); override;
function Init: boolean; // чруЁєчър DLL
function UnInit: boolean; // т√уЁєчър DLL
property OnHook: TNotifyEvent read _OnHook write _OnHook;
end;
type
TForm1 = class(TForm)
btStart: TButton;
btStop: TButton;
laCnt: TLabel;
me: TMemo;
tm: TTimer;
procedure FormCreate(Sender: TObject);
procedure btStartClick(Sender: TObject);
procedure btStopClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure tmTimer(Sender: TObject);
private
_Cnt: longint;
public
Hook: THook;
procedure OnHook (aSender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function SystemErrorStr (ErrCode: longint = -1): string;
var
ErrStr: string[255];
begin
if (ErrCode = -1) then ErrCode := GetLastError;
byte(ErrStr[0]) := FormatMessage (Format_Message_From_System, nil,
ErrCode, 0, @ErrStr[1], 253, nil);
Result := Trim(ErrStr);
end;
procedure THook.CreateParams (var Params: TCreateParams);
begin
inherited;
with Params do
Style := Style and (not ws_Child);
end;
constructor THook.Create (anOwner: TComponent);
begin
inherited;
LastErr := 0;
_FName := ExtractFilePath(ParamStr(0)) + 'hook_KM.dll';
_WM_KeybdHook := RegisterWindowMessage ('WM_KEYBD_HOOK');
_WM_MouseHook := RegisterWindowMessage ('WM_MOUSE_HOOK');
_DLL := 0;
_SetProc := nil;
end;
function THook.Init: boolean;
begin
UnInit;
Result := False; LastErr := 0;
try
repeat
_DLL := LoadLibrary (PChar(_FName)); if ( _DLL = 0 ) then break;
_SetProc := GetProcAddress (_DLL, 'SetHook'); if not Assigned(_SetProc) then break;
Result := ( _SetProc (True, Handle) = 0 );
until True;
if not Result then LastErr := GetLastError;
except
UnInit;
raise;
end;
end;
function THook.UnInit: boolean;
begin
Result := True; LastErr := 0;
if (_DLL <> 0) then begin
if Assigned(_SetProc) then LastErr := _SetProc (False, 0);
Result := ( LastErr = 0 );
FreeLibrary (_DLL);
end;
_DLL := 0;
_SetProc := nil;
end;
procedure THook.WndProc (var aMsg: TMessage);
begin
inherited;
with aMsg do begin
if ( Msg = _WM_KeybdHook ) or
( Msg = _WM_MouseHook )
then begin
if Assigned (_OnHook) then _OnHook (Self);
end;
end;
end;
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
procedure TForm1.FormCreate(Sender: TObject);
begin
_Cnt := 0;
Hook := THook.Create (Self);
Hook.OnHook := OnHook;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Hook.UnInit;
end;
procedure TForm1.btStartClick(Sender: TObject);
begin
if not Hook.Init then
me.Lines.Add (SystemErrorStr (Hook.LastErr));
end;
procedure TForm1.btStopClick(Sender: TObject);
begin
if not Hook.UnInit then
me.Lines.Add (SystemErrorStr (Hook.LastErr));
end;
procedure TForm1.OnHook(aSender: TObject);
begin
Inc (_Cnt);
end;
procedure TForm1.tmTimer(Sender: TObject);
begin
laCnt.Caption := IntToStr (_Cnt);
end;
end.
|
|
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
tinimi
Зарегистрирован: 27.03.2005 Сообщения: 90 Откуда: Win32
|
Добавлено: Пн Ноя 14 2005 22:04 Заголовок сообщения: |
|
|
Ну лекарство я тебе не дам, но:
Код: |
repeat
_DLL := LoadLibrary (PChar(_FName)); if ( _DLL = 0 ) then break;
_SetProc := GetProcAddress (_DLL, 'SetHook'); if not Assigned(_SetProc) then break;
Result := ( _SetProc (True, Handle) = 0 );
until True;
|
- а не легче было написать что-то типа:
Код: | procedure SetHook; external 'KBDHook.dll'; |
и зачем тебе ето:
Код: | _WM_KeybdHook := RegisterWindowMessage ('WM_KEYBD_HOOK');
_WM_MouseHook := RegisterWindowMessage ('WM_MOUSE_HOOK'); |
И еще - я не нашел где ты ставиш хуки. Есть SetWindowsHookEx в процеде SetHook.
Короче, почитай WinAPI и Delphi еще че нить. И пиши по проще!
WinApi придумали что бы упростить все, а по твоему коду етого не видно.
Как оказалось атачи сдесь выложить низя, по етому напиши мне на tinimi<at>gmail<dot>com _________________ [ TiNiMi ] |
|
Вернуться к началу |
|
![](templates/subSilver/images/spacer.gif) |
|