David_m43
asked on
Delphi Component
Hi Experts!
I am writing a components. One of the feature of compnents is to respond to Escape key even the component does not have the focus. I am wondering is there is any way i can achieve this functionality for my component. Please if any body can help me explain how i can achieve this functionality. The most important feature is if an Esc key is detected is for the component to run its new method.
Thank You
Zahid.
I am writing a components. One of the feature of compnents is to respond to Escape key even the component does not have the focus. I am wondering is there is any way i can achieve this functionality for my component. Please if any body can help me explain how i can achieve this functionality. The most important feature is if an Esc key is detected is for the component to run its new method.
Thank You
Zahid.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The real question is if your component should do that at all.
It is either a windowed control which means that it can focus and should only react to keys when focused
or it is a non-windowed control which should not react to keys at all.
It is either a windowed control which means that it can focus and should only react to keys when focused
or it is a non-windowed control which should not react to keys at all.
Another way is to register a HotKey
Here's my version....
unit MyComponent;
interface
uses
Windows, Messages, SysUtils, Classes,Controls;
type
TMyComponent = class(TComponent)
private
FEnabled: Boolean;
FRegistered: Boolean;
prOldWndProc: TWndMethod;
FHotkey: TSHortcut;
FOnHotKeyPressed: TNotifyEvent;
prWindow: TWinControl;
prHandle: HWND;
procedure RegisterKey;
procedure UnRegisterKey;
{ Private declarations }
protected
{ Protected declarations }
procedure SetEnabled(const Value: Boolean);
procedure SetHotKey(const Value: TShortcut);
procedure NewWindowProc(var Message: TMessage);
procedure Loaded; override;
public
{ Public declarations }
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
property Registered: boolean read FRegistered;
published
{ Published declarations }
property Enabled: Boolean read FEnabled write SetEnabled default true;
property Key: TShortcut read FHotkey write SetHotkey;
property OnHotKey: TNotifyEvent read FOnHotKeyPressed write FOnHotKeyPressed;
end;
procedure Register;
implementation
{ TMyComponent }
constructor TMyComponent.Create(aOwner : TComponent);
begin
inherited;
FEnabled := True;
FHotKey := 0;
FRegistered := false;
if not (csDesigning in ComponentState) then
begin
prWindow := TWinControl(Self.Owner);
prOldWndProc := prWindow.WindowProc;
prWindow.WindowProc := NewWindowProc;
prHandle := prWindow.Handle;
end;
end;
destructor TMyComponent.Destroy;
begin
if not (csDesigning in ComponentState) then
begin
UnRegisterKey;
prWindow.WindowProc := prOldWndProc;
end;
inherited;
end;
procedure TMyComponent.Loaded;
begin
inherited;
if (FEnabled) and (not (csDesigning in ComponentState)) then RegisterKey;
end;
procedure TMyComponent.NewWindowProc (var Message: TMessage);
begin
case Message.Msg of
WM_HOTKEY:
begin
if assigned(FOnHotkeyPressed) then
FOnHotKeyPressed(self);
end;
end;
prOldWndProc(Message);
end;
procedure TMyComponent.RegisterKey;
procedure ShortCutToKey(ShortCut: TShortCut; var Key: Word; var Shift: TShiftState);
begin
Key := ShortCut and not (scShift + scCtrl + scAlt);
Shift := [];
if ShortCut and scShift <> 0 then Include(Shift, ssShift);
if ShortCut and scCtrl <> 0 then Include(Shift, ssCtrl);
if ShortCut and scAlt <> 0 then Include(Shift, ssAlt);
end;
var
lVKey: word;
lvShift: TShiftstate;
lModifier: UINT;
begin
if not FRegistered then
begin
lModifier := 0;
ShortcutToKey(fHotKey, lvKey, lvShift);
if ssShift in lvShift then
lModifier := lModifier or MOD_SHIFT;
if ssAlt in lvShift then
lModifier := lModifier or MOD_ALT;
if ssCtrl in lvShift then
lModifier := lModifier or MOD_CONTROL;
FRegistered := RegisterHotKey(prWindow.Ha ndle, 0, lModifier, LOBYTE(lVKey));
end;
end;
procedure TMyComponent.SetEnabled(co nst Value: Boolean);
begin
FEnabled := Value;
if FEnabled then
RegisterKey
else
UnregisterKey;
end;
procedure TMyComponent.UnRegisterKey ;
begin
if FRegistered then
begin
UnregisterHotKey(prHandle, 0);
FRegistered := False;
end;
end;
procedure TMyComponent.SetHotKey(con st Value: TShortcut);
begin
if Value <> FHotkey then
begin
FHotkey := Value;
if not (csDesigning in ComponentState) then
begin
UnRegisterKey;
if FEnabled then
RegisterKey;
end;
end;
end;
procedure Register;
begin
RegisterComponents('Sample s', [TMyComponent]);
end;
end.
the Key Shortcut value must be integer (in your case for Escape Key 27) but if you want to show it in object inspector like for the MenuItem Shorcut property you need a property editor...
Here's my version....
unit MyComponent;
interface
uses
Windows, Messages, SysUtils, Classes,Controls;
type
TMyComponent = class(TComponent)
private
FEnabled: Boolean;
FRegistered: Boolean;
prOldWndProc: TWndMethod;
FHotkey: TSHortcut;
FOnHotKeyPressed: TNotifyEvent;
prWindow: TWinControl;
prHandle: HWND;
procedure RegisterKey;
procedure UnRegisterKey;
{ Private declarations }
protected
{ Protected declarations }
procedure SetEnabled(const Value: Boolean);
procedure SetHotKey(const Value: TShortcut);
procedure NewWindowProc(var Message: TMessage);
procedure Loaded; override;
public
{ Public declarations }
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
property Registered: boolean read FRegistered;
published
{ Published declarations }
property Enabled: Boolean read FEnabled write SetEnabled default true;
property Key: TShortcut read FHotkey write SetHotkey;
property OnHotKey: TNotifyEvent read FOnHotKeyPressed write FOnHotKeyPressed;
end;
procedure Register;
implementation
{ TMyComponent }
constructor TMyComponent.Create(aOwner
begin
inherited;
FEnabled := True;
FHotKey := 0;
FRegistered := false;
if not (csDesigning in ComponentState) then
begin
prWindow := TWinControl(Self.Owner);
prOldWndProc := prWindow.WindowProc;
prWindow.WindowProc := NewWindowProc;
prHandle := prWindow.Handle;
end;
end;
destructor TMyComponent.Destroy;
begin
if not (csDesigning in ComponentState) then
begin
UnRegisterKey;
prWindow.WindowProc := prOldWndProc;
end;
inherited;
end;
procedure TMyComponent.Loaded;
begin
inherited;
if (FEnabled) and (not (csDesigning in ComponentState)) then RegisterKey;
end;
procedure TMyComponent.NewWindowProc
begin
case Message.Msg of
WM_HOTKEY:
begin
if assigned(FOnHotkeyPressed)
FOnHotKeyPressed(self);
end;
end;
prOldWndProc(Message);
end;
procedure TMyComponent.RegisterKey;
procedure ShortCutToKey(ShortCut: TShortCut; var Key: Word; var Shift: TShiftState);
begin
Key := ShortCut and not (scShift + scCtrl + scAlt);
Shift := [];
if ShortCut and scShift <> 0 then Include(Shift, ssShift);
if ShortCut and scCtrl <> 0 then Include(Shift, ssCtrl);
if ShortCut and scAlt <> 0 then Include(Shift, ssAlt);
end;
var
lVKey: word;
lvShift: TShiftstate;
lModifier: UINT;
begin
if not FRegistered then
begin
lModifier := 0;
ShortcutToKey(fHotKey, lvKey, lvShift);
if ssShift in lvShift then
lModifier := lModifier or MOD_SHIFT;
if ssAlt in lvShift then
lModifier := lModifier or MOD_ALT;
if ssCtrl in lvShift then
lModifier := lModifier or MOD_CONTROL;
FRegistered := RegisterHotKey(prWindow.Ha
end;
end;
procedure TMyComponent.SetEnabled(co
begin
FEnabled := Value;
if FEnabled then
RegisterKey
else
UnregisterKey;
end;
procedure TMyComponent.UnRegisterKey
begin
if FRegistered then
begin
UnregisterHotKey(prHandle,
FRegistered := False;
end;
end;
procedure TMyComponent.SetHotKey(con
begin
if Value <> FHotkey then
begin
FHotkey := Value;
if not (csDesigning in ComponentState) then
begin
UnRegisterKey;
if FEnabled then
RegisterKey;
end;
end;
end;
procedure Register;
begin
RegisterComponents('Sample
end;
end.
the Key Shortcut value must be integer (in your case for Escape Key 27) but if you want to show it in object inspector like for the MenuItem Shorcut property you need a property editor...
- you could lookup in a small intervall the keyboardstate
- GetAsyncKeyBoardState
- GetKeyBoardState
- you could hook the keyboard (dll needed)
- search for "hook keyboard" here