Slettet bruger
19. august 2008 - 17:57
#7
hej så er jeg hjemme. Det lader til at jeg har sourcen og ligeud af landevejen. Kan dog, ikke huske meget.
{A DLL is necessary for a system hook. The sample code below,
was found somewhere in dejanews. The first file shows the code
for a simple hook that would be placed in the dll. Next, a unit
is shown that provides basic interface to import the dll The
remaining comments are from the original author}
{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;
{$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);
{ 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.
(* Then have this importation unit: *)
{ This is a simple DLL import unit to give us access to the functions in
the HOOKDLL.PAS file. This is the unit your project will use.}
unit Hookunit;
interface
uses WinTypes;
function InstallSystemHook: boolean;
function InstallTaskHook: boolean;
function RemoveHook: boolean;
function IsHookSet: boolean;
{ Do not use InstallHook directly. Use InstallSystemHook or InstallTaskHook. }
function InstallHook(SystemHook: boolean; TaskHandle: THandle): boolean;
implementation
uses WinProcs;
const
HOOK_DLL = 'HOOKDLL.DLL';
function InstallHook(SystemHook: boolean;
TaskHandle: THandle): boolean; external HOOK_DLL;
function RemoveHook: boolean; external HOOK_DLL;
function IsHookSet: boolean; external HOOK_DLL;
function InstallSystemHook: boolean;
begin
InstallHook(TRUE, 0);
end;
function InstallTaskHook: boolean;
begin
InstallHook(FALSE,
{$IFDEF WIN32}
GetCurrentThreadID
{$ELSE}
GetCurrentTask
{$ENDIF}
);
end;
end.