Delphi Source Code
Search engine
HOME Components Tutorials Add Trick Links Contacts
ActiveX Components Database Files Forms Graphic Internet/Lan Math Miscellaneous Multimedia Printing Strings System Information Windows

Delphi source code for Windows >> Install a keyboard hook


Category: Windows
Title: Install a keyboard hook
Date added: 15.03.2006
Hits: 43845


{
Retrieve  what user types on the keyboard.
}


library HookLib;
uses
  madExcept,
  Windows,
  Messages,
  SysUtils;
type
  PHookRec = ^THookRec;
  THookRec = record
    AppHnd: Integer;
    MemoHnd: Integer;
  end;
var
  Hooked: Boolean;
  hKeyHook, hMemo, hMemFile, hApp: HWND;
  PHookRec1: PHookRec;

function KeyHookFunc(Code, VirtualKey, KeyStroke: Integer): LRESULT; stdcall;
var
  KeyState1: TKeyBoardState;
  AryChar: array[0..1] of Char;
  Count: Integer;
begin
  Result := 0;
  if Code = HC_NOREMOVE then Exit;
  Result := CallNextHookEx(hKeyHook, Code, VirtualKey, KeyStroke);
  {I moved the CallNextHookEx up here but if you want to block
   or change any keys then move it back down}

  if Code < 0 then
    Exit;
  if Code = HC_ACTION then
  begin
    if ((KeyStroke and (1 shl 30)) <> 0) then
      if not IsWindow(hMemo) then
      begin
       {I moved the OpenFileMapping up here so it would not be opened
        unless the app the DLL is attatched to gets some Key messages}

        hMemFile  := OpenFileMapping(FILE_MAP_WRITE, False, 'Global7v9k');
        PHookRec1 := MapViewOfFile(hMemFile, FILE_MAP_WRITE, 0, 0, 0);
        if PHookRec1 <> nil then
        begin
          hMemo := PHookRec1.MemoHnd;
          hApp  := PHookRec1.AppHnd;
        end;
      end;
    if ((KeyStroke and (1 shl 30)) <> 0) then
    begin
      GetKeyboardState(KeyState1);
      Count := ToAscii(VirtualKey, KeyStroke, KeyState1, AryChar, 0);
      if Count = 1 then
      begin
        SendMessage(hMemo, WM_CHAR, Ord(AryChar[0]), 0);
        {I included 2 ways to get the Charaters, a Memo Hnadle and
         a WM_USER+1678 message to the program}

        PostMessage(hApp, WM_USER + 1678, Ord(AryChar[0]), 0);
      end;
    end;
  end;
end;

function StartHook(MemoHandle, AppHandle: HWND): Byte; export;
begin
  Result := 0;
  if Hooked then
  begin
    Result := 1;
    Exit;
  end;
  if not IsWindow(MemoHandle) then
  begin
    Result := 4;
    Exit;
  end;
  hKeyHook := SetWindowsHookEx(WH_KEYBOARD, KeyHookFunc, hInstance, 0);
  if hKeyHook > 0 then
  begin
    {you need to use a mapped file because this DLL attatches to every app
     that gets windows messages when it's hooked, and you can't get info except
     through a Globally avaiable Mapped file}

    hMemFile := CreateFileMapping($FFFFFFFF, // $FFFFFFFF gets a page memory file
      nil,                // no security attributes
      PAGE_READWRITE,     // read/write access
      0,                  // size: high 32-bits
      SizeOf(THookRec),   // size: low 32-bits
      'Global7v9k');    // name of map object
    PHookRec1 := MapViewOfFile(hMemFile, FILE_MAP_WRITE, 0, 0, 0);
    hMemo := MemoHandle;
    PHookRec1.MemoHnd := MemoHandle;
    hApp := AppHandle;
    PHookRec1.AppHnd := AppHandle;
    {set the Memo and App handles to the mapped file}
    Hooked := True;
  end
  else
    Result := 2;
end;

function StopHook: Boolean; export;
begin
  if PHookRec1 <> nil then
  begin
    UnmapViewOfFile(PHookRec1);
    CloseHandle(hMemFile);
    PHookRec1 := nil;
  end;
  if Hooked then
    Result := UnhookWindowsHookEx(hKeyHook)
  else
    Result := True;
  Hooked := False;
end;

procedure EntryProc(dwReason: DWORD);
begin
  if (dwReason = Dll_Process_Detach) then
  begin
    if PHookRec1 <> nil then
    begin
      UnmapViewOfFile(PHookRec1);
      CloseHandle(hMemFile);
    end;
    UnhookWindowsHookEx(hKeyHook);
  end;
end;
exports
  StartHook,
  StopHook;
begin
  PHookRec1 := nil;
  Hooked := False;
  hKeyHook := 0;
  hMemo := 0;
  DLLProc := @EntryProc;
  EntryProc(Dll_Process_Attach);
end.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2. Code from the calling Program
{this program get's the Char from the DLL in 2 ways,
  as a Char message to a Memo and as a DLLMessage WM_USER+1678}

---
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
type
  TForm1 = class(TForm)
    but_StartHook: TButton;
    but_StopHook: TButton;
    label1: TLabel;
    Memo1: TMemo;
    
procedure but_StartHookClick(Sender: TObject);
    
procedure but_StopHookClick(Sender: TObject);
  private
    { Private declarations }
    hLib2: THandle;
    DllStr1: string;
    
procedure DllMessage(var Msg: TMessage); message WM_USER + 1678;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}

procedure TForm1.DllMessage(var Msg: TMessage);
begin
  if (Msg.wParam = 8) or (Msg.wParam = 13) then Exit;
  {the 8 is the Backspace and the 13 if the Enter key, You'll need to
  do some special handleing for a string}

  DllStr1 := DllStr1 + Chr(Msg.wParam);
  label1.Caption := DllStr1;
end;

procedure TForm1.but_StartHookClick(Sender: TObject);
type
  TStartHook = function(MemoHandle, AppHandle: HWND): Byte;
var
  StartHook1: TStartHook;
  SHresult: Byte;
begin
  hLib2 := LoadLibrary('HookLib.dll');
  @StartHook1 := GetProcAddress(hLib2, 'StartHook');
  if @StartHook1 = nil then Exit;
  SHresult := StartHook1(Memo1.Handle, Handle);
  if SHresult = 0 then ShowMessage('the Key Hook was Started, good');
  if SHresult = 1 then ShowMessage('the Key Hook was already Started');
  if SHresult = 2 then ShowMessage('the Key Hook can NOT be Started, bad');
  if SHresult = 4 then ShowMessage('MemoHandle is incorrect');
end;

procedure TForm1.but_StopHookClick(Sender: TObject);
type
  TStopHook = function: Boolean;
var
  StopHook1: TStopHook;
  hLib21: THandle;
begin
  @StopHook1 := GetProcAddress(hLib2, 'StopHook');
  if @StopHook1 = nil then
  begin
    ShowMessage('Stop Hook DLL Mem Addy not found');
    Exit;
  end;
  if StopHook1 then
    ShowMessage('Hook was stoped');
  FreeLibrary(hLib2);
  {for some reason in Win XP you need to call FreeLibrary twice
  maybe because you get 2 functions from the DLL? ?}

  FreeLibrary(hLib2);
end;
end.

Related Delphi Source Code:
Delphi Tricks
Delphi Tricks
For any problems or recommendations about Delphi Tricks site, please

feel free to contact us on that e-mail: support@delphitricks.com.
If you want to advertise on the site use that e-mail: advertise@delphitricks.com.

You can freely use or modify these Delphi source codes for non-commercial use. We are not responsible of any damages that can be caused by the utilisation of that source codes.

Copyright © 2006-2010 AVSoftware Company. All rights reserved.
Hide IP tricks