fibdev
asked on
System Wide Hooks (Hot Keys)
Hi,
I think the title of this question sais it all.
I need to create a system wide hook to trap keyboard events and execute a procedure. I hope someone has a answer for me that isn't too complex... I'm sorta' a newbie when it comes to Delphi.
Thanks
I think the title of this question sais it all.
I need to create a system wide hook to trap keyboard events and execute a procedure. I hope someone has a answer for me that isn't too complex... I'm sorta' a newbie when it comes to Delphi.
Thanks
listening
Here is some code that shows you how to do what you want using Hot Keys - it is from my PAQ (credit to ITugay). Note
that it is easy to modify it to only register the the particular hotkey you want:
This code hooks all possible keys and then resend it to recepient. Result will be shown in the Listbox1 in format "[Shift] KEY
ACTIVE_FORM_NAME", if KEY not in "!".."Z" then scancode will be shown.
The working sample is bellow:
------------------
type
TForm1 = class(TForm)
Listbox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
public
procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY;
procedure RegKeys;
procedure UnRegKeys;
end;
.........
procedure TForm1.RegKeys;
var I : integer;
begin
for I:=0 to 255 do
if I<>16 then // skip [Shift]
begin
RegisterHotKey(Handle,I,0,
RegisterHotKey(Handle,I+25
end;
end;
procedure TForm1.UnRegKeys;
var I : integer;
begin
for I:=0 to 511 do
UnregisterHotKey(Handle,I)
end;
procedure TForm1.WMHotKey(var Msg : TWMHotKey);
var NameBuf : array[0..1000] of char;
FormName : string;
Key : string;
Ch : char;
begin
SetLength(FormName,GetWind
Move(NameBuf,pointer(FormN
if MSG.HotKey > 255 then
begin
MSG.HotKey:=MSG.HotKey-256
Key:='[Shift]+';
end else Key:='';
Ch:=Char(MapVirtualKey(MSG
if Ch = ' ' then Key:=Key+'[ ]' else
if Ch in [#33..#127]
then Key:=Key+Ch
else Key:=Key+'['+IntToStr(Msg.
Listbox1.Items.Add(Key+' '+FormName);
Listbox1.ItemIndex:=Listbo
UnregKeys; // avoid recursion
keybd_event(MSG.HotKey,MSG
RegKeys;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RegKeys;
end;
procedure TForm1.FormDestroy(Sender:
begin
UnregKeys;
end;
There are also hotkey components availbale from DSP (http://sunsite.icm.edu.pl/delphi) and Torries (www.torry.ru)
Cheers,
Raymond.
If you need SYSTEM WIDE, let me know, I have some code
ASKER
Ok, let me be specific...
Here is what I want to do:
I want Ctrl + Alt + W to fire procedure TForm1.Window1Click(Sender : TObject);
I want Ctrl + Alt + S to fire procedure TForm1.Screen1Click(Sender : TObject);
I want Ctrl + Alt + A to fire procedure TForm1.SelectedArea1Click( Sender: TObject);
Explain how to set this up. Keep in find I'm a newbie so explain it like you would a 5 year old.
Thanks
Here is what I want to do:
I want Ctrl + Alt + W to fire procedure TForm1.Window1Click(Sender
I want Ctrl + Alt + S to fire procedure TForm1.Screen1Click(Sender
I want Ctrl + Alt + A to fire procedure TForm1.SelectedArea1Click(
Explain how to set this up. Keep in find I'm a newbie so explain it like you would a 5 year old.
Thanks
ASKER
errr .... keep in mind, not keep in find :)
I can give an answer when question is unlocked...although 50 pts is a it low... rwilson???
ASKER
Ok, sorry rwilson, I just need more input.
As far as the points go ... I don't have many more (25 pts left to spend) If I get a good answer I'll come off of these left over points.
As far as the points go ... I don't have many more (25 pts left to spend) If I get a good answer I'll come off of these left over points.
The code presented below shows how to create a keyboard, mouse and shell event loop. (unfortunately, I was asked to create a computer activity monitor at work) Hopefully, you will make better use of it....
In order to create a system wide hook, you need a DLL to handle the hook.
This LIBRARY project will create a DLL to do just this. (more code and explanation after this unit)
========================== ========== ========== =======
library HookLib;
uses Windows;
//this should really be in an include file! [MY]
const
MSG_MY_KEY_EVENT = 'MY_KEY_EVENT_HOOK';
MSG_MY_SHELL_EVENT = 'MY_SHELL_EVENT_HOOK';
MSG_MY_MOUSE_EVENT = 'MY_MOUSE_EVENT_HOOK';
HookMemFileName = 'MYHook.DTA';
HookMutexName = 'MYHookMutex';
type TShared=record
ShellHook: HHook;
ShellCount: integer; //# of shell hooks
KeyHook: HHOOK;
KeyCount: integer;//# of keyboard hooks
MouseHook: HHOOK;
MouseCount: integer; //# of mouse hooks
Receiver:Integer;//app currently processing a hook in this DLL. Only one at a time for now [MY]
AttachCount:Integer;//how many apps are attached to this DLL
end;
PShared=^TShared;
TWatchType=(wtSHELL,wtKEYB OARD,wtMOU SE);
var
MemFile, HookMutex: THandle;
Shared: PShared;
SHELL_EVENT,MOUSE_EVENT,KE Y_EVENT: integer;
function GetShellHook( Code: Integer;wParam: WPARAM;lParam:LPARAM): LRESULT; stdcall;
begin
if Code>=0 then PostMessage(Shared^.Receiv er,SHELL_E VENT,wPara m,Code);
Result := CallNextHookEx(Shared^.She llHook, Code, wParam, lParam);
end;
function GetKeyHook( Code: Integer;wParam: WPARAM;lParam:LPARAM): LRESULT; stdcall;
begin
if code=HC_ACTION then PostMessage(Shared^.Receiv er,KEY_EVE NT,wParam, lParam);
Result := CallNextHookEx(Shared^.Key Hook, Code, wParam, lParam);
end;
function GetMouseHook( Code: Integer;wParam: WPARAM;lParam:LPARAM): LRESULT; stdcall;
begin
if code=HC_ACTION then PostMessage(Shared^.Receiv er,MOUSE_E VENT,wPara m,lParam);
Result := CallNextHookEx(Shared^.Mou seHook, Code, wParam, lParam);
end;
procedure StartWatching(WatchType:TW atchType); stdcall;
begin
try
WaitForSingleObject(HookMu tex,INFINI TE);
with Shared^ do
begin
case WatchType of
wtSHELL:
begin
if (ShellCount=0) and (ShellHook=0) then
ShellHook:=SetWindowsHookE x(WH_SHELL , @GetShellHook, HInstance,0);
inc(ShellCount);
end;
wtKEYBOARD:
begin
if (KeyCount=0) and (KeyHook=0) then
KeyHook:=SetWindowsHookEx( WH_KEYBOAR D, @GetKeyHook, HInstance , 0);
inc(KeyCount);
end;
wtMouse:
begin
if (MouseCount=0) and (MouseHook=0) then
MouseHook:=SetWindowsHookE x(WH_Mouse , @GetMouseHook, HInstance , 0);
inc(MouseCount);
end;
end;
end;
finally
ReleaseMutex(HookMutex);
end;
end;
procedure StopWatching(WatchType:TWa tchType); stdcall;
begin
try
WaitForSingleObject(HookMu tex,INFINI TE);
with Shared^ do
begin
case WatchType of
wtSHELL:
begin
dec(ShellCount);
if (ShellCount<=0) and (ShellHook<>0) then
begin
UnhookWindowsHookEx(ShellH ook);
ShellHook:=0;
ShellCount:=0;
end;
end;
wtKEYBOARD:
begin
dec(KeyCount);
if (KeyCount<=0) and (KeyHook<>0) then
begin
UnhookWindowsHookEx(KeyHoo k);
KeyHook:=0;
KeyCount:=0;
end;
end;
wtMouse:
begin
dec(MouseCount);
if (MouseCount<=0) and (MouseHook<>0) then
begin
UnhookWindowsHookEx(MouseH ook);
MouseHook:=0;
MouseCount:=0;
end;
end;
end;
end;
finally
ReleaseMutex(HookMutex);
end;
end;
procedure StopAll;stdcall;//stops all hook activity
var alreadyStopped:Boolean;
begin
try
WaitForSingleObject(HookMu tex,INFINI TE);
with Shared^ do
begin
alreadyStopped:=((ShellCou nt=0) and (KeyCount=0) and (MouseCount=0));
ShellCount:=0;
KeyCount:=0;
MouseCount:=0;
end;
finally
ReleaseMutex(HookMutex);
end;
if not alreadyStopped then
begin
StopWatching(wtSHELL);
StopWatching(wtKEYBOARD);
StopWatching(wtMouse);
end;
end;
//This needs to be rewritten for multiple receivers! [MY]
procedure SetReceiver(R:Integer); stdcall;
begin
try
WaitForSingleObject(HookMu tex,INFINI TE);
Shared^.Receiver:=r;
finally
ReleaseMutex(HookMutex);
end;
end;
function StillWatching:Boolean; stdcall;
begin
try
WaitForSingleObject(HookMu tex,INFINI TE);
result:=(Shared^.ShellCoun t>0) or (Shared^.KeyCount>0);
finally
ReleaseMutex(HookMutex);
end;
end;
procedure StartUp;
begin
SHELL_EVENT:=RegisterWindo wMessage(P Char(MSG_M Y_SHELL_EV ENT));
KEY_EVENT:=RegisterWindowM essage(PCh ar(MSG_MY_ KEY_EVENT) );
MOUSE_EVENT:=RegisterWindo wMessage(P Char(MSG_M Y_MOUSE_EV ENT));
HookMutex:=CreateMutex(nil ,True,Hook MutexName) ;
MemFile:=OpenFileMapping(F ILE_MAP_WR ITE,False, HookMemFil eName);
if MemFile=0 then MemFile:=CreateFileMapping ($FFFFFFFF ,nil,
PAGE_READWRITE,0,SizeOf(TS hared),Hoo kMemFileNa me);
Shared:=MapViewOfFile(MemF ile,FILE_M AP_WRITE,0 ,0,0);
if MemFile=0 then FillChar(Shared^,SizeOf(TS hared),0);
Inc(Shared^.AttachCount);
ReleaseMutex(HookMutex);
end;
procedure DLLEntryPoint(reason:integ er);
var
Unused: Boolean;
begin
case reason of
DLL_PROCESS_DETACH:
begin
try
WaitForSingleObject(HookMu tex,INFINI TE);
dec(Shared^.AttachCount);
Unused:=(Shared^.AttachCou nt=0);
finally
ReleaseMutex(HookMutex);
end;
if Unused then
begin
StopAll;
UnmapViewOfFile(Shared);
CloseHandle(MemFile);
CloseHandle(HookMutex);
end;
end;
DLL_PROCESS_ATTACH: Startup;
end;
end;
exports
StartWatching,
StopWatching,
StopAll,
StillWatching,
SetReceiver;
begin
Startup;
DLLProc:=@DLLEntryPoint;
end.
========================== ========== ========== =======
This component encapsulates the interface with the DLL (after this code, an example of using this component)
========================== ========== ========== =======
unit HookLibIntf;
interface
uses Windows,Classes,Messages,F orms,Dialo gs;
const
MSG_MY_KEY_EVENT = 'MY_KEY_EVENT_HOOK';
MSG_MY_SHELL_EVENT = 'MY_SHELL_EVENT_HOOK';
MSG_MY_MOUSE_EVENT = 'MY_MOUSE_EVENT_HOOK';
type
TWatchType=(wtSHELL,wtKEYB OARD,wtMOU SE);
TWatching=procedure(WatchT ype:TWatch Type); stdcall;
TStopAll=procedure; stdcall;
TStillWatching=function:Bo olean; stdcall;
TSetReceiver=procedure(r:I nteger); stdcall;
TShellEvent=procedure(Send er: TObject;wParam: WPARAM;code: integer) of object;
TMouseKeyEvent=procedure(S ender: TObject;wParam: WPARAM;lParam: LPARAM) of object;
type THookLib=class(TComponent)
private
HWNDHandle:THandle;
LibHandle:THandle;
SHELL_EVENT: Cardinal;
Mouse_EVENT: Cardinal;
KEY_EVENT: Cardinal;
StartWatching:TWatching;
StopWatching:TWatching;
StopAll:TStopAll;
StillWatching:TStillWatchi ng;
SetReceiver:TSetReceiver;
FOnKeyEvent: TMouseKeyEvent;
FOnMouseEvent: TMouseKeyEvent;
FOnShellEvent: TShellEvent;
procedure LoadLib;
procedure SetOnKeyEvent(const Value: TMouseKeyEvent);
procedure SetOnMouseEvent(const Value: TMouseKeyEvent);
procedure SetOnShellEvent(const Value: TShellEvent);
procedure UnloadLib;
protected
procedure OnShellHook(nCode: Integer; wParam: Longint);virtual;
procedure OnMouseHook(wParam,lParam: Longint);virtual;
procedure OnKeyHook(wParam, lParam: Integer);virtual;
public
procedure OnHWNDEvent(var Message: TMessage);
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
procedure Start(WatchType:TWatchType );
procedure Stop(WatchType:TWatchType) ;
published
property OnShellEvent: TShellEvent read FOnShellEvent write SetOnShellEvent;
property OnMouseEvent: TMouseKeyEvent read FOnMouseEvent write SetOnMouseEvent;
property OnKeyEvent: TMouseKeyEvent read FOnKeyEvent write SetOnKeyEvent;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('System ',[THookLi b]);
end;
{ THookLib }
constructor THookLib.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// get unique Message IDs for the Broadcast of the dll
SHELL_EVENT:=RegisterWindo wMessage(P Char(MSG_M Y_SHELL_EV ENT));
KEY_EVENT:=RegisterWindowM essage(PCh ar(MSG_MY_ KEY_EVENT) );
MOUSE_EVENT:=RegisterWindo wMessage(P Char(MSG_M Y_MOUSE_EV ENT));
LibHandle:=0;
StartWatching:=nil;
StopWatching:=nil;
StopAll:=nil;
StillWatching:=nil;
HWNDHandle:=0;
end;
destructor THookLib.Destroy;
begin
if assigned(StopAll) then StopAll;
UnLoadLib;
inherited Destroy;
end;
procedure THookLib.LoadLib;
begin
if (LibHandle=0) and (not (csDesigning in ComponentState)) then
begin
LibHandle:=LoadLibrary('ho oklib.dll' );
if LibHandle<>0 then
begin
HWNDHandle:=AllocateHwnd(O nHWNDEvent );
@StartWatching:=GetProcAdd ress(LibHa ndle, 'StartWatching');
@StopWatching:=GetProcAddr ess(LibHan dle, 'StopWatching');
@StillWatching:=GetProcAdd ress(LibHa ndle, 'StillWatching');
@StopAll:=GetProcAddress(L ibHandle, 'StopAll');
@SetReceiver:=GetProcAddre ss(LibHand le, 'SetReceiver');
if assigned(SetReceiver) then SetReceiver(HWNDHandle);
end;
if (LibHandle=0) or (not assigned(StartWatching))
or (not assigned(StopWatching)) or (not assigned(StillWatching))
or (not assigned(StopAll)) then
begin
if LibHandle=0 then MessageDlg('hooklib.dll not found!',mtError,[mbOK],0)
else MessageDlg('hooklib.dll is not valid',mtError,[mbOK],0);
LibHandle:=0;
StartWatching:=nil;
StopWatching:=nil;
StopAll:=nil;
StillWatching:=nil;
end;
end;
end;
procedure THookLib.OnHWNDEvent(var Message: TMessage);
begin
if Message.Msg=SHELL_EVENT then OnShellHook(Message.lParam ,Message.w Param)
else if Message.Msg=Mouse_EVENT then OnMouseHook(Message.wParam ,Message.l Param)
else if Message.Msg=KEY_EVENT then OnKeyHook(Message.wParam,M essage.lPa ram)
else Message.Result:= DefWindowProc(HWNDHandle, Message.Msg, Message.wParam, Message.lParam);
end;
procedure THookLib.OnKeyHook(wParam, lParam: Integer);
begin
if Assigned(FOnKeyEvent) then FOnKeyEvent(self,wParam,lP aram);
end;
procedure THookLib.OnMouseHook(wPara m, lParam: Integer);
begin
if Assigned(FOnMouseEvent) then FOnMouseEvent(self,wParam, lParam);
end;
procedure THookLib.OnShellHook(nCode , wParam: Integer);
begin
if Assigned(FOnShellEvent) then FOnShellEvent(self,wParam, nCode);
end;
procedure THookLib.SetOnKeyEvent(con st Value: TMouseKeyEvent);
begin
FOnKeyEvent := Value;
end;
procedure THookLib.SetOnMouseEvent(c onst Value: TMouseKeyEvent);
begin
FOnMouseEvent := Value;
end;
procedure THookLib.SetOnShellEvent(c onst Value: TShellEvent);
begin
FOnShellEvent := Value;
end;
procedure THookLib.Start(WatchType: TWatchType);
begin
LoadLib;
if assigned(StartWatching) then StartWatching(WatchType);
end;
procedure THookLib.Stop(WatchType: TWatchType);
begin
if (libHandle<>0) and assigned(StopWatching) then
begin
StopWatching(WatchType);
if not StillWatching then UnLoadLib;
end;
end;
procedure THookLib.UnLoadLib;
begin
if HWNDHandle<>0 then DeallocateHwnd(HWNDHandle) ;
if LibHandle<>0 then FreeLibrary(LibHandle);
LibHandle:=0;
StartWatching:=nil;
StopWatching:=nil;
StopAll:=nil;
StillWatching:=nil;
HWNDHandle:=0;
end;
end.
========================== ========== ========== =======
An example of using the component and the DLL.
========================== ========== ========== =======
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, HookLibIntf;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
HookLib1: THookLib;
Label1: TLabel;
Label2: TLabel;
procedure HookLib1KeyEvent(Sender: TObject; wParam, lParam: Integer);
procedure HookLib1MouseEvent(Sender: TObject; wParam, lParam: Integer);
procedure HookLib1ShellEvent(Sender: TObject; wParam, code: Integer);
procedure FormShow(Sender: TObject);
private
MouseCount: integer;
KeyboardCount: integer;
LastTitle: string;
public
{ Public declarations }
end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormShow(Sender: TObject);
begin
HookLib1.Start(wtSHELL);
HookLib1.Start(wtKEYBOARD) ;
HookLib1.Start(wtMouse);
MouseCount:=0;
KeyboardCount:=0;
LastTitle:='dasilhljkasdfh ';
end;
procedure TForm1.HookLib1KeyEvent(Se nder: TObject; wParam,
lParam: Integer);
begin
Inc(KeyboardCount);
Label2.Caption:=Format('%d ',[Keyboar dCount]);
end;
procedure TForm1.HookLib1MouseEvent( Sender: TObject; wParam,
lParam: Integer);
begin
Inc(MouseCount);
Label1.Caption:=Format('%d ',[MouseCo unt]);
end;
procedure TForm1.HookLib1ShellEvent( Sender: TObject; wParam,
code: Integer);
var
Title: array[0..300] of Char;
begin
case code of
HSHELL_ACTIVATESHELLWINDOW : Memo1.Lines.Add(Format('%s DESKTOP',[FormatDateTime(' c',Now)])) ;
HSHELL_WINDOWACTIVATED,HSH ELL_REDRAW :
begin
if GetWindowText(wParam,Title ,299)=0 then Title[0]:=#0;
if LastTitle<>Title then
begin
Memo1.Lines.Add(Format('%s %s',[FormatDateTime('c',No w),Title]) );
LastTitle:=Title;
end;
end;
end;
end;
In order to create a system wide hook, you need a DLL to handle the hook.
This LIBRARY project will create a DLL to do just this. (more code and explanation after this unit)
==========================
library HookLib;
uses Windows;
//this should really be in an include file! [MY]
const
MSG_MY_KEY_EVENT = 'MY_KEY_EVENT_HOOK';
MSG_MY_SHELL_EVENT = 'MY_SHELL_EVENT_HOOK';
MSG_MY_MOUSE_EVENT = 'MY_MOUSE_EVENT_HOOK';
HookMemFileName = 'MYHook.DTA';
HookMutexName = 'MYHookMutex';
type TShared=record
ShellHook: HHook;
ShellCount: integer; //# of shell hooks
KeyHook: HHOOK;
KeyCount: integer;//# of keyboard hooks
MouseHook: HHOOK;
MouseCount: integer; //# of mouse hooks
Receiver:Integer;//app currently processing a hook in this DLL. Only one at a time for now [MY]
AttachCount:Integer;//how many apps are attached to this DLL
end;
PShared=^TShared;
TWatchType=(wtSHELL,wtKEYB
var
MemFile, HookMutex: THandle;
Shared: PShared;
SHELL_EVENT,MOUSE_EVENT,KE
function GetShellHook( Code: Integer;wParam: WPARAM;lParam:LPARAM): LRESULT; stdcall;
begin
if Code>=0 then PostMessage(Shared^.Receiv
Result := CallNextHookEx(Shared^.She
end;
function GetKeyHook( Code: Integer;wParam: WPARAM;lParam:LPARAM): LRESULT; stdcall;
begin
if code=HC_ACTION then PostMessage(Shared^.Receiv
Result := CallNextHookEx(Shared^.Key
end;
function GetMouseHook( Code: Integer;wParam: WPARAM;lParam:LPARAM): LRESULT; stdcall;
begin
if code=HC_ACTION then PostMessage(Shared^.Receiv
Result := CallNextHookEx(Shared^.Mou
end;
procedure StartWatching(WatchType:TW
begin
try
WaitForSingleObject(HookMu
with Shared^ do
begin
case WatchType of
wtSHELL:
begin
if (ShellCount=0) and (ShellHook=0) then
ShellHook:=SetWindowsHookE
inc(ShellCount);
end;
wtKEYBOARD:
begin
if (KeyCount=0) and (KeyHook=0) then
KeyHook:=SetWindowsHookEx(
inc(KeyCount);
end;
wtMouse:
begin
if (MouseCount=0) and (MouseHook=0) then
MouseHook:=SetWindowsHookE
inc(MouseCount);
end;
end;
end;
finally
ReleaseMutex(HookMutex);
end;
end;
procedure StopWatching(WatchType:TWa
begin
try
WaitForSingleObject(HookMu
with Shared^ do
begin
case WatchType of
wtSHELL:
begin
dec(ShellCount);
if (ShellCount<=0) and (ShellHook<>0) then
begin
UnhookWindowsHookEx(ShellH
ShellHook:=0;
ShellCount:=0;
end;
end;
wtKEYBOARD:
begin
dec(KeyCount);
if (KeyCount<=0) and (KeyHook<>0) then
begin
UnhookWindowsHookEx(KeyHoo
KeyHook:=0;
KeyCount:=0;
end;
end;
wtMouse:
begin
dec(MouseCount);
if (MouseCount<=0) and (MouseHook<>0) then
begin
UnhookWindowsHookEx(MouseH
MouseHook:=0;
MouseCount:=0;
end;
end;
end;
end;
finally
ReleaseMutex(HookMutex);
end;
end;
procedure StopAll;stdcall;//stops all hook activity
var alreadyStopped:Boolean;
begin
try
WaitForSingleObject(HookMu
with Shared^ do
begin
alreadyStopped:=((ShellCou
ShellCount:=0;
KeyCount:=0;
MouseCount:=0;
end;
finally
ReleaseMutex(HookMutex);
end;
if not alreadyStopped then
begin
StopWatching(wtSHELL);
StopWatching(wtKEYBOARD);
StopWatching(wtMouse);
end;
end;
//This needs to be rewritten for multiple receivers! [MY]
procedure SetReceiver(R:Integer); stdcall;
begin
try
WaitForSingleObject(HookMu
Shared^.Receiver:=r;
finally
ReleaseMutex(HookMutex);
end;
end;
function StillWatching:Boolean; stdcall;
begin
try
WaitForSingleObject(HookMu
result:=(Shared^.ShellCoun
finally
ReleaseMutex(HookMutex);
end;
end;
procedure StartUp;
begin
SHELL_EVENT:=RegisterWindo
KEY_EVENT:=RegisterWindowM
MOUSE_EVENT:=RegisterWindo
HookMutex:=CreateMutex(nil
MemFile:=OpenFileMapping(F
if MemFile=0 then MemFile:=CreateFileMapping
PAGE_READWRITE,0,SizeOf(TS
Shared:=MapViewOfFile(MemF
if MemFile=0 then FillChar(Shared^,SizeOf(TS
Inc(Shared^.AttachCount);
ReleaseMutex(HookMutex);
end;
procedure DLLEntryPoint(reason:integ
var
Unused: Boolean;
begin
case reason of
DLL_PROCESS_DETACH:
begin
try
WaitForSingleObject(HookMu
dec(Shared^.AttachCount);
Unused:=(Shared^.AttachCou
finally
ReleaseMutex(HookMutex);
end;
if Unused then
begin
StopAll;
UnmapViewOfFile(Shared);
CloseHandle(MemFile);
CloseHandle(HookMutex);
end;
end;
DLL_PROCESS_ATTACH: Startup;
end;
end;
exports
StartWatching,
StopWatching,
StopAll,
StillWatching,
SetReceiver;
begin
Startup;
DLLProc:=@DLLEntryPoint;
end.
==========================
This component encapsulates the interface with the DLL (after this code, an example of using this component)
==========================
unit HookLibIntf;
interface
uses Windows,Classes,Messages,F
const
MSG_MY_KEY_EVENT = 'MY_KEY_EVENT_HOOK';
MSG_MY_SHELL_EVENT = 'MY_SHELL_EVENT_HOOK';
MSG_MY_MOUSE_EVENT = 'MY_MOUSE_EVENT_HOOK';
type
TWatchType=(wtSHELL,wtKEYB
TWatching=procedure(WatchT
TStopAll=procedure; stdcall;
TStillWatching=function:Bo
TSetReceiver=procedure(r:I
TShellEvent=procedure(Send
TMouseKeyEvent=procedure(S
type THookLib=class(TComponent)
private
HWNDHandle:THandle;
LibHandle:THandle;
SHELL_EVENT: Cardinal;
Mouse_EVENT: Cardinal;
KEY_EVENT: Cardinal;
StartWatching:TWatching;
StopWatching:TWatching;
StopAll:TStopAll;
StillWatching:TStillWatchi
SetReceiver:TSetReceiver;
FOnKeyEvent: TMouseKeyEvent;
FOnMouseEvent: TMouseKeyEvent;
FOnShellEvent: TShellEvent;
procedure LoadLib;
procedure SetOnKeyEvent(const Value: TMouseKeyEvent);
procedure SetOnMouseEvent(const Value: TMouseKeyEvent);
procedure SetOnShellEvent(const Value: TShellEvent);
procedure UnloadLib;
protected
procedure OnShellHook(nCode: Integer; wParam: Longint);virtual;
procedure OnMouseHook(wParam,lParam:
procedure OnKeyHook(wParam, lParam: Integer);virtual;
public
procedure OnHWNDEvent(var Message: TMessage);
constructor Create(AOwner:TComponent);
destructor Destroy; override;
procedure Start(WatchType:TWatchType
procedure Stop(WatchType:TWatchType)
published
property OnShellEvent: TShellEvent read FOnShellEvent write SetOnShellEvent;
property OnMouseEvent: TMouseKeyEvent read FOnMouseEvent write SetOnMouseEvent;
property OnKeyEvent: TMouseKeyEvent read FOnKeyEvent write SetOnKeyEvent;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('System
end;
{ THookLib }
constructor THookLib.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// get unique Message IDs for the Broadcast of the dll
SHELL_EVENT:=RegisterWindo
KEY_EVENT:=RegisterWindowM
MOUSE_EVENT:=RegisterWindo
LibHandle:=0;
StartWatching:=nil;
StopWatching:=nil;
StopAll:=nil;
StillWatching:=nil;
HWNDHandle:=0;
end;
destructor THookLib.Destroy;
begin
if assigned(StopAll) then StopAll;
UnLoadLib;
inherited Destroy;
end;
procedure THookLib.LoadLib;
begin
if (LibHandle=0) and (not (csDesigning in ComponentState)) then
begin
LibHandle:=LoadLibrary('ho
if LibHandle<>0 then
begin
HWNDHandle:=AllocateHwnd(O
@StartWatching:=GetProcAdd
@StopWatching:=GetProcAddr
@StillWatching:=GetProcAdd
@StopAll:=GetProcAddress(L
@SetReceiver:=GetProcAddre
if assigned(SetReceiver) then SetReceiver(HWNDHandle);
end;
if (LibHandle=0) or (not assigned(StartWatching))
or (not assigned(StopWatching)) or (not assigned(StillWatching))
or (not assigned(StopAll)) then
begin
if LibHandle=0 then MessageDlg('hooklib.dll not found!',mtError,[mbOK],0)
else MessageDlg('hooklib.dll is not valid',mtError,[mbOK],0);
LibHandle:=0;
StartWatching:=nil;
StopWatching:=nil;
StopAll:=nil;
StillWatching:=nil;
end;
end;
end;
procedure THookLib.OnHWNDEvent(var Message: TMessage);
begin
if Message.Msg=SHELL_EVENT then OnShellHook(Message.lParam
else if Message.Msg=Mouse_EVENT then OnMouseHook(Message.wParam
else if Message.Msg=KEY_EVENT then OnKeyHook(Message.wParam,M
else Message.Result:= DefWindowProc(HWNDHandle, Message.Msg, Message.wParam, Message.lParam);
end;
procedure THookLib.OnKeyHook(wParam,
begin
if Assigned(FOnKeyEvent) then FOnKeyEvent(self,wParam,lP
end;
procedure THookLib.OnMouseHook(wPara
begin
if Assigned(FOnMouseEvent) then FOnMouseEvent(self,wParam,
end;
procedure THookLib.OnShellHook(nCode
begin
if Assigned(FOnShellEvent) then FOnShellEvent(self,wParam,
end;
procedure THookLib.SetOnKeyEvent(con
begin
FOnKeyEvent := Value;
end;
procedure THookLib.SetOnMouseEvent(c
begin
FOnMouseEvent := Value;
end;
procedure THookLib.SetOnShellEvent(c
begin
FOnShellEvent := Value;
end;
procedure THookLib.Start(WatchType: TWatchType);
begin
LoadLib;
if assigned(StartWatching) then StartWatching(WatchType);
end;
procedure THookLib.Stop(WatchType: TWatchType);
begin
if (libHandle<>0) and assigned(StopWatching) then
begin
StopWatching(WatchType);
if not StillWatching then UnLoadLib;
end;
end;
procedure THookLib.UnLoadLib;
begin
if HWNDHandle<>0 then DeallocateHwnd(HWNDHandle)
if LibHandle<>0 then FreeLibrary(LibHandle);
LibHandle:=0;
StartWatching:=nil;
StopWatching:=nil;
StopAll:=nil;
StillWatching:=nil;
HWNDHandle:=0;
end;
end.
==========================
An example of using the component and the DLL.
==========================
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, HookLibIntf;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
HookLib1: THookLib;
Label1: TLabel;
Label2: TLabel;
procedure HookLib1KeyEvent(Sender: TObject; wParam, lParam: Integer);
procedure HookLib1MouseEvent(Sender:
procedure HookLib1ShellEvent(Sender:
procedure FormShow(Sender: TObject);
private
MouseCount: integer;
KeyboardCount: integer;
LastTitle: string;
public
{ Public declarations }
end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormShow(Sender: TObject);
begin
HookLib1.Start(wtSHELL);
HookLib1.Start(wtKEYBOARD)
HookLib1.Start(wtMouse);
MouseCount:=0;
KeyboardCount:=0;
LastTitle:='dasilhljkasdfh
end;
procedure TForm1.HookLib1KeyEvent(Se
lParam: Integer);
begin
Inc(KeyboardCount);
Label2.Caption:=Format('%d
end;
procedure TForm1.HookLib1MouseEvent(
lParam: Integer);
begin
Inc(MouseCount);
Label1.Caption:=Format('%d
end;
procedure TForm1.HookLib1ShellEvent(
code: Integer);
var
Title: array[0..300] of Char;
begin
case code of
HSHELL_ACTIVATESHELLWINDOW
HSHELL_WINDOWACTIVATED,HSH
begin
if GetWindowText(wParam,Title
if LastTitle<>Title then
begin
Memo1.Lines.Add(Format('%s
LastTitle:=Title;
end;
end;
end;
end;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Ok...
How do I change your example so it executes the procedures when the above listed hotkeys are pressed?
So far I've been able to incorperate it into my project and create the dll and component. All I need help with now is the example.
Thanks for your help!
How do I change your example so it executes the procedures when the above listed hotkeys are pressed?
So far I've been able to incorperate it into my project and create the dll and component. All I need help with now is the example.
Thanks for your help!
This is the routine of interest:
procedure TForm1.HookLib1KeyEvent(Se nder: TObject; wParam,
lParam: Integer);
begin
Inc(KeyboardCount);
Label2.Caption:=Format('%d ',[Keyboar dCount]);
end;
In my case, I was only interested in counting keystrokes. In your case, you want to interpret wParam and lParam to see what key was pressed.
wParam
Specifies the virtual-key code of the key that generated the keystroke message.
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. This parameter can be a combination of the following values:
Value Description
0-15 Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
16-23 Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24 Specifies whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
25-28 Reserved.
29 Specifies the context code. The value is 1 if the ALT key is down; otherwise, it is 0.
30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.
example:
case wParam of
VK_F9: --the F9 key was pressed (in any application)
end;
procedure TForm1.HookLib1KeyEvent(Se
lParam: Integer);
begin
Inc(KeyboardCount);
Label2.Caption:=Format('%d
end;
In my case, I was only interested in counting keystrokes. In your case, you want to interpret wParam and lParam to see what key was pressed.
wParam
Specifies the virtual-key code of the key that generated the keystroke message.
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. This parameter can be a combination of the following values:
Value Description
0-15 Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
16-23 Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24 Specifies whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
25-28 Reserved.
29 Specifies the context code. The value is 1 if the ALT key is down; otherwise, it is 0.
30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.
example:
case wParam of
VK_F9: --the F9 key was pressed (in any application)
end;
ASKER
Adjusted points from 50 to 75
ASKER
Could you post an example of how this should look If I want to trap:
Alt + Ctrl + W and fire a procedure
Thank you for your time and I will give you the points.
I'm not very good at this stuff and I need to be led along, sorry for that...
Alt + Ctrl + W and fire a procedure
Thank you for your time and I will give you the points.
I'm not very good at this stuff and I need to be led along, sorry for that...
Let me show you how to find out (as I suspect you need more key codes)
procedure TForm1.HookLib1KeyEvent(Se nder: TObject; wParam,
lParam: Integer);
begin
case wParam of
VK_F9: ShowMessage('F9 pressed');
end;
end;
1) place a break point at the line that reads case wParam of
2) run the program
3) press CTRL+ALT+W
4) the program will break at the specified line. note the value of wParam and lParam.
5) repeat step 3
warning:
first you will get scan code for Alt, then Ctrl+Alt and finally Ctrl+Alt+W
procedure TForm1.HookLib1KeyEvent(Se
lParam: Integer);
begin
case wParam of
VK_F9: ShowMessage('F9 pressed');
end;
end;
1) place a break point at the line that reads case wParam of
2) run the program
3) press CTRL+ALT+W
4) the program will break at the specified line. note the value of wParam and lParam.
5) repeat step 3
warning:
first you will get scan code for Alt, then Ctrl+Alt and finally Ctrl+Alt+W
ASKER
Crud!
I've been having this problem, but it didn't interfere until now.
When I try to run this project in the delphi enviorment I get the CPU debugger and I have no clue about what to do with it or how to resolve the problem. Until now, I've just been compiling the project and using the run command to execute the exe file.
Here is a screenshot of the cpu window
http://fibdev.com/temp/cpu.jpg
I don't know if you know what this means, but is there another way to get this information, other than by way of breakpoints?
I've been having this problem, but it didn't interfere until now.
When I try to run this project in the delphi enviorment I get the CPU debugger and I have no clue about what to do with it or how to resolve the problem. Until now, I've just been compiling the project and using the run command to execute the exe file.
Here is a screenshot of the cpu window
http://fibdev.com/temp/cpu.jpg
I don't know if you know what this means, but is there another way to get this information, other than by way of breakpoints?
1) are you compiling with debug information.
2) just hit F9 when you get the CPU window to keep running
3) there is no way, although I can guess
VK_ALT VK_CTRL Ord('W')
you will get these three events (one for each key) in ANY order.
4) try with 1 key first, to see how it works. use my VK_F9 example
Tony
2) just hit F9 when you get the CPU window to keep running
3) there is no way, although I can guess
VK_ALT VK_CTRL Ord('W')
you will get these three events (one for each key) in ANY order.
4) try with 1 key first, to see how it works. use my VK_F9 example
Tony
ASKER
Tony...
I must be doing something wronge because nothing happens when I fallow your instruction :(
This is so frustrating, thanks for your help
I must be doing something wronge because nothing happens when I fallow your instruction :(
This is so frustrating, thanks for your help
1) clear all break points.
2) do this in your code
procedure TForm1.HookLib1KeyEvent(Se nder: TObject; wParam,
lParam: Integer);
begin
case wParam of
VK_F9: ShowMessage('F9 pressed');
end;
end;
3) run program
4) press F9 in any program
5) does message box appear?
Check:
1)
HookLib1.Start(wtSHELL);
===> HookLib1.Start(wtKEYBOARD) ;
HookLib1.Start(wtMouse);
this must be called to set hooks.
2) the DLL must be in same directory or on path
2) do this in your code
procedure TForm1.HookLib1KeyEvent(Se
lParam: Integer);
begin
case wParam of
VK_F9: ShowMessage('F9 pressed');
end;
end;
3) run program
4) press F9 in any program
5) does message box appear?
Check:
1)
HookLib1.Start(wtSHELL);
===> HookLib1.Start(wtKEYBOARD)
HookLib1.Start(wtMouse);
this must be called to set hooks.
2) the DLL must be in same directory or on path
you do have the event handler from the component assigned to the code , don't you?
ASKER
I don't understand this...
I'm doing everything you say, but I'm not having any luck. I know I'm doing something wrong... I just don't know what!
Does this question pertain to the component code, or the example?
Please bare with me because I am so lame at this. :)
"you do have the event handler from the component assigned to the code , don't you?"
I'm doing everything you say, but I'm not having any luck. I know I'm doing something wrong... I just don't know what!
Does this question pertain to the component code, or the example?
Please bare with me because I am so lame at this. :)
"you do have the event handler from the component assigned to the code , don't you?"
Reyou three source code files
1) the DLL. I assume you built this
2) the component. I assume you installed the component.
3) a form on your program. You put the component on it and assign the OnKeyEvent event. This event will be triggered whenever a key is pressed in any program on the system.
try the code I gave above in this event handler
4) somewhere in your code, you must call the HookLib1.Start(wtKEYBOARD) ;
(assuming HookLib1 is the name of the component)
1) the DLL. I assume you built this
2) the component. I assume you installed the component.
3) a form on your program. You put the component on it and assign the OnKeyEvent event. This event will be triggered whenever a key is pressed in any program on the system.
try the code I gave above in this event handler
4) somewhere in your code, you must call the HookLib1.Start(wtKEYBOARD)
(assuming HookLib1 is the name of the component)
ASKER
I don't get it...
I did all those things, but when I try to press F9, nothing happens!
What could I be doing wrong?
I did all those things, but when I try to press F9, nothing happens!
What could I be doing wrong?
ASKER
Ok,
I got it working, but it looks like for every time I press F9 I get two message boxes?
I got it working, but it looks like for every time I press F9 I get two message boxes?
email me at ads@houston.rr.com
I will send you the project and executable (I just tested it again, it works like I said)
I will send you the project and executable (I just tested it again, it works like I said)
one for key down, one for key up
look at lParam, bit 31:
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. This parameter can be a combination of the following values:
Value Description
0-15 Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
16-23 Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24 Specifies whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
25-28 Reserved.
29 Specifies the context code. The value is 1 if the ALT key is down; otherwise, it is 0.
30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.
If you got this to work from another app, such as notepad, then I believe I have answered your original question. You now have code for global keyboard hook (and mouse and shell too)
look at lParam, bit 31:
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag. This parameter can be a combination of the following values:
Value Description
0-15 Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user's holding down the key.
16-23 Specifies the scan code. The value depends on the original equipment manufacturer (OEM).
24 Specifies whether the key is an extended key, such as a function key or a key on the numeric keypad. The value is 1 if the key is an extended key; otherwise, it is 0.
25-28 Reserved.
29 Specifies the context code. The value is 1 if the ALT key is down; otherwise, it is 0.
30 Specifies the previous key state. The value is 1 if the key is down before the message is sent; it is 0 if the key is up.
31 Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released.
If you got this to work from another app, such as notepad, then I believe I have answered your original question. You now have code for global keyboard hook (and mouse and shell too)
nice piece of work orascript
ASKER
Answer accepted
ASKER
Well...
I'm still at a loss with all of this. I don't have the hok keys I asked for, but I do have an F9 key that fires on press and release. Thanks anyway, you tried really hard.
I'm still at a loss with all of this. I don't have the hok keys I asked for, but I do have an F9 key that fires on press and release. Thanks anyway, you tried really hard.
ASKER
How do I use this lParam?
I know you've helped me so much, but I'm still at a bit of a loss here.
I know you've helped me so much, but I'm still at a bit of a loss here.
what is this" thanks anyway...."
you asked for a system wide key hook, you got a system wide key hook, not just for F9, but for any key.
I really do not understand the grading, this is a very difficult quesytion with very limited points, the least you could have done is award an A for the effort I have put in...
you asked for a system wide key hook, you got a system wide key hook, not just for F9, but for any key.
I really do not understand the grading, this is a very difficult quesytion with very limited points, the least you could have done is award an A for the effort I have put in...
OK, I am p*ssed off.
Orascript: You should know what a hot key is - it is a system wide key handler. It is NOT necessary to write a global system keyboard hook to implement one. Your comment is pretty damn blatant and not acceptable. Unfortunately the weekend intervened and I didn't get back to EE until now, only to discover this cr*p.
fibdev: If you want to get what you want to work, then go back to my original answer and look at the API help for registerhotkey, this documents the flags you pass to request CTRL/ALT etc.
Cheers,
Raymond.
Orascript: You should know what a hot key is - it is a system wide key handler. It is NOT necessary to write a global system keyboard hook to implement one. Your comment is pretty damn blatant and not acceptable. Unfortunately the weekend intervened and I didn't get back to EE until now, only to discover this cr*p.
fibdev: If you want to get what you want to work, then go back to my original answer and look at the API help for registerhotkey, this documents the flags you pass to request CTRL/ALT etc.
Cheers,
Raymond.
rwilson, sorry, I should have researched your answer more before posting, no I was not familiar with RegisterHotKey.
I have asked community support to reassign the points to you
https://www.experts-exchange.com/jsp/qShow.jsp?ta=commspt&qid=10481138
I have asked community support to reassign the points to you
https://www.experts-exchange.com/jsp/qShow.jsp?ta=commspt&qid=10481138
orascript: You are a gentleman. Sorry if I was a bit strong... I was miffed...
Cheers,
Raymond.
Cheers,
Raymond.
no, you are right, I am sometimes hasty in my judgement. If EE does not come through, let me know, I will give you the points myself, worth it, I learned something today (RegisterHotKey)...
Hello everyone,
rwilson, please post an answer at:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=10490698
darinw
Customer Service
rwilson, please post an answer at:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=10490698
darinw
Customer Service
ASKER
Sorry to cause hard fealings. I do appreciate all the work that was put into this and I'm sorry that I don't have many points to work with.
My original posting:
Hi,
I think the title of this question sais it all.
I need to create a system wide hook to trap keyboard events and execute a procedure. I hope someone has a answer for me that isn't too complex... I'm sorta' a newbie when it comes to Delphi.
Thanks
Clearly states that I needed to capture a keyboard event and... execute a function. So, clearly my question wasn't answered in it's entirety. I felt as if I was being pushed to award the points, and so I did.
At this point, I even clarified my needs:
Ok, let me be specific...
Here is what I want to do:
I want Ctrl + Alt + W to fire procedure TForm1.Window1Click(Sender : TObject);
I want Ctrl + Alt + S to fire procedure TForm1.Screen1Click(Sender : TObject);
I want Ctrl + Alt + A to fire procedure TForm1.SelectedArea1Click( Sender: TObject);
Explain how to set this up. Keep in mind I'm a newbie so explain it like you would a 5 year old.
Thanks
Again, sorry to upset you, but my question was not answered. I do acknowlage that you worked very hard to resolve this for me, but I gave up my points and still don't have a usable solution. I have been on vacation for the past week, or I would have addressed this sooner!
My original posting:
Hi,
I think the title of this question sais it all.
I need to create a system wide hook to trap keyboard events and execute a procedure. I hope someone has a answer for me that isn't too complex... I'm sorta' a newbie when it comes to Delphi.
Thanks
Clearly states that I needed to capture a keyboard event and... execute a function. So, clearly my question wasn't answered in it's entirety. I felt as if I was being pushed to award the points, and so I did.
At this point, I even clarified my needs:
Ok, let me be specific...
Here is what I want to do:
I want Ctrl + Alt + W to fire procedure TForm1.Window1Click(Sender
I want Ctrl + Alt + S to fire procedure TForm1.Screen1Click(Sender
I want Ctrl + Alt + A to fire procedure TForm1.SelectedArea1Click(
Explain how to set this up. Keep in mind I'm a newbie so explain it like you would a 5 year old.
Thanks
Again, sorry to upset you, but my question was not answered. I do acknowlage that you worked very hard to resolve this for me, but I gave up my points and still don't have a usable solution. I have been on vacation for the past week, or I would have addressed this sooner!
OK, here are the goods:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.WMHotKey(var Msg : TWMHotKey);
begin
case Msg.HotKey of
1: ShowMessage('Call TForm1.Window1Click(Sender : TObject);');
2: ShowMessage('Call TForm1.Screen1Click(Sender : TObject);');
3: ShowMessage('Call TForm1.SelectedArea1Click( Sender: TObject);');
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterHotKey(Handle,1,MO D_CONTROL + MOD_ALT, ord('W'));
RegisterHotKey(Handle,2,MO D_CONTROL + MOD_ALT, ord('S'));
RegisterHotKey(Handle,3,MO D_CONTROL + MOD_ALT, ord('A'));
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle,1) ;
UnregisterHotKey(Handle,1) ;
UnregisterHotKey(Handle,1) ;
end;
end.
Cheers,
Raymond.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.WMHotKey(var Msg : TWMHotKey);
begin
case Msg.HotKey of
1: ShowMessage('Call TForm1.Window1Click(Sender
2: ShowMessage('Call TForm1.Screen1Click(Sender
3: ShowMessage('Call TForm1.SelectedArea1Click(
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterHotKey(Handle,1,MO
RegisterHotKey(Handle,2,MO
RegisterHotKey(Handle,3,MO
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle,1)
UnregisterHotKey(Handle,1)
UnregisterHotKey(Handle,1)
end;
end.
Cheers,
Raymond.
Oops, FormClose should be:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle,1) ;
UnregisterHotKey(Handle,2) ;
UnregisterHotKey(Handle,3) ;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle,1)
UnregisterHotKey(Handle,2)
UnregisterHotKey(Handle,3)
end;
ASKER
Thank you Raymond...
It works perfectly!
Could you tell me how to set it up so that it executes the procedure in stead of displaying the message. I know this is a topic far more advanced than my skills (or lack thereof). I've only got 30 points, but you can have them.
It works perfectly!
Could you tell me how to set it up so that it executes the procedure in stead of displaying the message. I know this is a topic far more advanced than my skills (or lack thereof). I've only got 30 points, but you can have them.
ASKER
If possible, I want to set focus to my application before executing the function. I don't know it that will make the process more difficult or easier.
Thank you
Thank you
Well, you would do it like this:
procedure TForm1.WMHotKey(var Msg : TWMHotKey);
begin
SetForegroundWindow(Handle );
case Msg.HotKey of
1: Window1Click(Self);
2: Screen1Click(Self);
3: SelectedArea1Click(Self);
end;
end;
You will need to add the window, screen and selectedarea (menu items) and create the click events for this to compile.
Don't worry abvout the points, keep them for your next Q.
Cheers,
Raymond.
procedure TForm1.WMHotKey(var Msg : TWMHotKey);
begin
SetForegroundWindow(Handle
case Msg.HotKey of
1: Window1Click(Self);
2: Screen1Click(Self);
3: SelectedArea1Click(Self);
end;
end;
You will need to add the window, screen and selectedarea (menu items) and create the click events for this to compile.
Don't worry abvout the points, keep them for your next Q.
Cheers,
Raymond.
Best (Amster)damned 7 points I ever spent.