home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 March / Chip_1998-03_cd.bin / zkuste / delphi / ruzkomp / WINHOOK.ZIP / Hookdll.dpr next >
Text File  |  1997-05-19  |  7KB  |  168 lines

  1. {                                                                         }
  2. { This is the core of the system and task hook.  Some notes:              }
  3. {                                                                         }
  4. {  1)  You will definitely want to give the file a more descriptive name  }
  5. {      to avoid possible collisions with other DLL names.                 }
  6. {  2)  Edit the MouseHookCallBack function to do what you need when a     }
  7. {      mouse message is received.  If you are hooking something other     }
  8. {      mouse messages, see the SetWindowsHookEx topic in the help for the }
  9. {      proper WH_xxxx constant, and any notes about the particular type   }
  10. {      of hook.                                                           }
  11. {  3)  If an application that uses the DLL crashes while the hook is      }
  12. {      installed, all manner of wierd things can happen, depending on the }
  13. {      sort of thing you are doing in the callback.  The best suggestion  }
  14. {      is to use a utility that displays loaded DLLs and forcibly unload  }
  15. {      the DLL.  You could also write a simple app that checks to see if  }
  16. {      the DLL is loaded, and if so, call FreeModule until it returns 0.  }
  17. {  4)  If you make changes to the DLL but the changes don't seem to be    }
  18. {      working, you may have the DLL already loaded in memory.  Remember, }
  19. {      loading a DLL that is already in memory just increments a usage    }
  20. {      count in Windows and uses the already loaded copy.                 }
  21. {  5)  Remember when you are hooking in at the *system* level, your       }
  22. {      callback function is being called for everything in the OS.  Try   }
  23. {      to keep the processing in the callback as tight and fast as you    }
  24. {      possibly can.                                                      }
  25. {  6)  Be careful of the uses clause.  If you include stuff like Dialogs, }
  26. {      you will end up linking in a lot of the VCL, and have a DLL that   }
  27. {      comes out compiled to around 250k.  You would probably be better   }
  28. {      served using WM_USER messages to communicate with the application. }
  29. {  7)  I have successfully hooked mouse messages without the use of a     }
  30. {      DLL, but many of the hooks say they require the callback to be in  }
  31. {      a DLL, so I am hesitant to include this method.  It certainly      }
  32. {      makes the build/test cycle *much* easier, but since it is not      }
  33. {      "sanctioned" by MS, I would stay away from it and discourage it.   }
  34. {                                                                         }
  35.  
  36. library HookDLL;
  37.  
  38. uses WinTypes, WinProcs, Messages;
  39.  
  40.  
  41. var
  42.   HookCount: integer;
  43.   HookHandle: HHook;
  44.  
  45.  
  46. { This is where you do your special processing. }
  47. {$IFDEF WIN32}
  48. function MouseHookCallBack(Code: integer; Msg: WPARAM; MouseHook: LPARAM): LRESULT; stdcall;
  49. {$ELSE}
  50. function MouseHookCallBack(Code: integer; Msg: word; MouseHook: longint): longint; export;
  51. {$ENDIF}
  52. begin
  53.   { If the value of Code is less than 0, we are not allowed to do anything except pass }
  54.   { it on to the next hook procedure immediately.                                      }
  55.   if Code >= 0 then begin
  56.     { This example does nothing except beep when the right mouse button is pressed. }
  57.     if Msg = WM_RBUTTONDOWN then
  58.       MessageBeep(1);
  59. { This is probably closer to what you would want to do...
  60.     case Msg of:
  61.       WM_LBUTTONDOWN:
  62.         begin
  63.         end;
  64.       WM_LBUTTONUP:
  65.         begin
  66.         end;
  67.       WM_LBUTTONDBLCLK:
  68.         begin
  69.         end;
  70.       WM_RBUTTONDOWN:
  71.         begin
  72.         end;
  73.       WM_RBUTTONUP:
  74.         begin
  75.         end;
  76.       WM_RBUTTONDBLCLK:
  77.         begin
  78.         end;
  79.       WM_MBUTTONDOWN:
  80.         begin
  81.         end;
  82.       WM_MBUTTONUP:
  83.         begin
  84.         end;
  85.       WM_MBUTTONDBLCLK:
  86.         begin
  87.         end;
  88.       WM_MOUSEMOVE:
  89.         begin
  90.         end;
  91.     end;}
  92.  
  93.     { If you handled the situation, and don't want Windows to process the }
  94.     { message, do *NOT* execute the next line.  Be very sure this is what }
  95.     { want, though.  If you don't pass on stuff like WM_MOUSEMOVE, you    }
  96.     { will NOT like the results you get.                                  }
  97.     Result := CallNextHookEx(HookHandle, Code, Msg, MouseHook);
  98.   end else
  99.     Result := CallNextHookEx(HookHandle, Code, Msg, MouseHook);
  100. end;
  101.  
  102. { Call InstallHook to set the hook. }
  103. function InstallHook(SystemHook: boolean; TaskHandle: THandle) : boolean; export;
  104.   { This is really silly, but that's the way it goes.  The only way to get the  }
  105.   { module handle, *not* instance, is from the filename.  The Microsoft example }
  106.   { just hard-codes the DLL filename.  I think this is a little bit better.     }
  107.   function GetModuleHandleFromInstance: THandle;
  108.   var
  109.     s: array[0..512] of char;
  110.   begin
  111.     { Find the DLL filename from the instance value. }
  112.     GetModuleFileName(hInstance, s, sizeof(s)-1);
  113.     { Find the handle from the filename. }
  114.     Result := GetModuleHandle(s);
  115.   end;
  116. begin
  117.   { Technically, this procedure could do nothing but call SetWindowsHookEx(),  }
  118.   { but it is probably better to be sure about things, and not set the hook    }
  119.   { more than once.  You definitely don't want your callback being called more }
  120.   { than once per message, do you?                                             }
  121.   Result := TRUE;
  122.   if HookCount = 0 then begin
  123.     if SystemHook then
  124.       HookHandle := SetWindowsHookEx(WH_MOUSE, MouseHookCallBack, HInstance, 0)
  125.     else
  126.       { See the Microsoft KnowledgeBase, PSS ID Number: Q92659, for a discussion of }
  127.       { the Windows bug that requires GetModuleHandle() to be used.                 }
  128.       HookHandle := SetWindowsHookEx(WH_MOUSE, MouseHookCallBack,
  129.                                      GetModuleHandleFromInstance, TaskHandle);
  130.     if HookHandle <> 0 then
  131.       inc(HookCount)
  132.     else
  133.       Result := FALSE;
  134.   end else
  135.     inc(HookCount);
  136. end;
  137.  
  138. { Call RemoveHook to remove the system hook. }
  139. function RemoveHook: boolean; export;
  140. begin
  141.   { See if our reference count is down to 0, and if so then unhook. }
  142.   Result := FALSE;
  143.   if HookCount < 1 then exit;
  144.   Result := TRUE;
  145.   dec(HookCount);
  146.   if HookCount = 0 then
  147.     Result := UnhookWindowsHookEx(HookHandle);
  148. end;
  149.  
  150. { Have we hooked into the system? }
  151. function IsHookSet: boolean; export;
  152. begin
  153.   Result := (HookCount > 0) and (HookHandle <> 0);
  154. end;
  155.  
  156. exports
  157.   InstallHook,
  158.   RemoveHook,
  159.   IsHookSet,
  160.   MouseHookCallBack;
  161.  
  162. { Initialize DLL data. }
  163. begin
  164.   HookCount := 0;
  165.   HookHandle := 0;
  166. end.
  167.  
  168.