home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 March
/
Chip_1998-03_cd.bin
/
zkuste
/
delphi
/
ruzkomp
/
WINHOOK.ZIP
/
Hookdll.dpr
next >
Wrap
Text File
|
1997-05-19
|
7KB
|
168 lines
{ }
{ This is the core of the system and task hook. Some notes: }
{ }
{ 1) You will definitely want to give the file a more descriptive name }
{ to avoid possible collisions with other DLL names. }
{ 2) Edit the MouseHookCallBack function to do what you need when a }
{ mouse message is received. If you are hooking something other }
{ mouse messages, see the SetWindowsHookEx topic in the help for the }
{ proper WH_xxxx constant, and any notes about the particular type }
{ of hook. }
{ 3) If an application that uses the DLL crashes while the hook is }
{ installed, all manner of wierd things can happen, depending on the }
{ sort of thing you are doing in the callback. The best suggestion }
{ is to use a utility that displays loaded DLLs and forcibly unload }
{ the DLL. You could also write a simple app that checks to see if }
{ the DLL is loaded, and if so, call FreeModule until it returns 0. }
{ 4) If you make changes to the DLL but the changes don't seem to be }
{ working, you may have the DLL already loaded in memory. Remember, }
{ loading a DLL that is already in memory just increments a usage }
{ count in Windows and uses the already loaded copy. }
{ 5) Remember when you are hooking in at the *system* level, your }
{ callback function is being called for everything in the OS. Try }
{ to keep the processing in the callback as tight and fast as you }
{ possibly can. }
{ 6) Be careful of the uses clause. If you include stuff like Dialogs, }
{ you will end up linking in a lot of the VCL, and have a DLL that }
{ comes out compiled to around 250k. You would probably be better }
{ served using WM_USER messages to communicate with the application. }
{ 7) I have successfully hooked mouse messages without the use of a }
{ DLL, but many of the hooks say they require the callback to be in }
{ a DLL, so I am hesitant to include this method. It certainly }
{ makes the build/test cycle *much* easier, but since it is not }
{ "sanctioned" by MS, I would stay away from it and discourage it. }
{ }
library HookDLL;
uses WinTypes, WinProcs, Messages;
var
HookCount: integer;
HookHandle: HHook;
{ This is where you do your special processing. }
{$IFDEF WIN32}
function MouseHookCallBack(Code: integer; Msg: WPARAM; MouseHook: LPARAM): LRESULT; stdcall;
{$ELSE}
function MouseHookCallBack(Code: integer; Msg: word; MouseHook: longint): longint; export;
{$ENDIF}
begin
{ If the value of Code is less than 0, we are not allowed to do anything except pass }
{ it on to the next hook procedure immediately. }
if Code >= 0 then begin
{ This example does nothing except beep when the right mouse button is pressed. }
if Msg = WM_RBUTTONDOWN then
MessageBeep(1);
{ This is probably closer to what you would want to do...
case Msg of:
WM_LBUTTONDOWN:
begin
end;
WM_LBUTTONUP:
begin
end;
WM_LBUTTONDBLCLK:
begin
end;
WM_RBUTTONDOWN:
begin
end;
WM_RBUTTONUP:
begin
end;
WM_RBUTTONDBLCLK:
begin
end;
WM_MBUTTONDOWN:
begin
end;
WM_MBUTTONUP:
begin
end;
WM_MBUTTONDBLCLK:
begin
end;
WM_MOUSEMOVE:
begin
end;
end;}
{ If you handled the situation, and don't want Windows to process the }
{ message, do *NOT* execute the next line. Be very sure this is what }
{ want, though. If you don't pass on stuff like WM_MOUSEMOVE, you }
{ will NOT like the results you get. }
Result := CallNextHookEx(HookHandle, Code, Msg, MouseHook);
end else
Result := CallNextHookEx(HookHandle, Code, Msg, MouseHook);
end;
{ Call InstallHook to set the hook. }
function InstallHook(SystemHook: boolean; TaskHandle: THandle) : boolean; export;
{ This is really silly, but that's the way it goes. The only way to get the }
{ module handle, *not* instance, is from the filename. The Microsoft example }
{ just hard-codes the DLL filename. I think this is a little bit better. }
function GetModuleHandleFromInstance: THandle;
var
s: array[0..512] of char;
begin
{ Find the DLL filename from the instance value. }
GetModuleFileName(hInstance, s, sizeof(s)-1);
{ Find the handle from the filename. }
Result := GetModuleHandle(s);
end;
begin
{ Technically, this procedure could do nothing but call SetWindowsHookEx(), }
{ but it is probably better to be sure about things, and not set the hook }
{ more than once. You definitely don't want your callback being called more }
{ than once per message, do you? }
Result := TRUE;
if HookCount = 0 then begin
if SystemHook then
HookHandle := SetWindowsHookEx(WH_MOUSE, MouseHookCallBack, HInstance, 0)
else
{ See the Microsoft KnowledgeBase, PSS ID Number: Q92659, for a discussion of }
{ the Windows bug that requires GetModuleHandle() to be used. }
HookHandle := SetWindowsHookEx(WH_MOUSE, MouseHookCallBack,
GetModuleHandleFromInstance, TaskHandle);
if HookHandle <> 0 then
inc(HookCount)
else
Result := FALSE;
end else
inc(HookCount);
end;
{ Call RemoveHook to remove the system hook. }
function RemoveHook: boolean; export;
begin
{ See if our reference count is down to 0, and if so then unhook. }
Result := FALSE;
if HookCount < 1 then exit;
Result := TRUE;
dec(HookCount);
if HookCount = 0 then
Result := UnhookWindowsHookEx(HookHandle);
end;
{ Have we hooked into the system? }
function IsHookSet: boolean; export;
begin
Result := (HookCount > 0) and (HookHandle <> 0);
end;
exports
InstallHook,
RemoveHook,
IsHookSet,
MouseHookCallBack;
{ Initialize DLL data. }
begin
HookCount := 0;
HookHandle := 0;
end.