4

Is it ok if i use it like this..for multiple events?

unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Clipbrd;

type
  TForm4 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure WMHotkey(var Message: TWMHotKey); message WM_HOTKEY;
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

const
  MY_ID = 123;
  MY_ID1 = 123;
  MY_ID2 = 123;

{$R *.dfm}

procedure TForm4.FormCreate(Sender: TObject);
begin
  RegisterHotKey(Handle, MY_ID, MOD_CONTROL, ord('1'));
   RegisterHotKey(Handle, MY_ID1, MOD_CONTROL, ord('2'));
    RegisterHotKey(Handle, MY_ID2, MOD_CONTROL, ord('3'));
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
  UnregisterHotKey(Handle, MY_ID);
  UnregisterHotKey(Handle, MY_ID1);
  UnregisterHotKey(Handle, MY_ID2);
end;

procedure TForm4.WMHotkey(var Message: TWMHotKey);
begin
  if Message.HotKey = MY_ID then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'text1';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

    if Message.HotKey = MY_ID1 then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'text2';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

  if Message.HotKey = MY_ID2 then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'text3';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

  end;
end;

end;
end;
end.
menjaraz
  • 7,551
  • 4
  • 41
  • 81
andrei
  • 41
  • 1
  • 3

3 Answers3

6

Use the RegisterHotKey function. If you want the application to be invisible, you might want all the details in my answer to a similar question.

Try this:

unit Unit4;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Clipbrd;

type
  TForm4 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure WMHotkey(var Message: TWMHotKey); message WM_HOTKEY;
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

const
  MY_ID = 123;

{$R *.dfm}

procedure TForm4.FormCreate(Sender: TObject);
begin
  RegisterHotKey(Handle, MY_ID, MOD_CONTROL, ord('1'));
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
  UnregisterHotKey(Handle, MY_ID);
end;

procedure TForm4.WMHotkey(var Message: TWMHotKey);
begin
  if Message.HotKey = MY_ID then
  begin

    if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then
      RaiseLastOSError;

    try
      Clipboard.AsText := 'This is my own text!';
      SendMessage(GetFocus, WM_PASTE, 0, 0);
    finally
      AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), false);
    end;

  end;
end;

end.

Of course, you will need to use this approach and modify it so it suits your particular case. (That is, you probably want something more than an application that prints "This is my own text!" on Ctrl+1, but nothing else.)

Community
  • 1
  • 1
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • can u give me an example please? – andrei Nov 06 '10 at 22:18
  • let's say when i press ctrl+1 the word delphi appears on every windows app, like microsoft word or so – andrei Nov 06 '10 at 22:19
  • @andrei: I now give an example of this very thing. But it seems not work in Word 2010 at least (but Notepad works fine). – Andreas Rejbrand Nov 06 '10 at 22:35
  • Andreas you just use `UnregisterHotKey` function when you uses the `RegisterHotKey` to free the hotkey. – RRUZ Nov 06 '10 at 22:46
  • I know. I was just sloppy to demonstrate the idea to the OP. – Andreas Rejbrand Nov 06 '10 at 22:47
  • @RRUZ: I assumed you meant "you **must** use". – Andreas Rejbrand Nov 06 '10 at 22:49
  • @RUZZ: Still, I am curious: are you sure? Doesn't the operating system remove the registration when the process is terminated? – Andreas Rejbrand Nov 06 '10 at 22:58
  • Andreas about your question, yes i'm sure about that, you can check the MSDN documentatation wich says `..the application must explicitly call UnregisterHotKey to unregister the old hot key.` in this link http://msdn.microsoft.com/en-us/library/ms646309%28VS.85%29.aspx – RRUZ Nov 07 '10 at 01:36
  • i'm afraid it doesnt do anything my friend... i pasted your code, run the app, open notepad, pressed ctrl+1 and absolutely nothing happens... – andrei Nov 07 '10 at 19:02
  • I think it works. Are you sure that Notepad had keyboard focus when you pressed Ctrl+1? @RRUZ: Doesn't it work for you? – Andreas Rejbrand Nov 07 '10 at 19:07
  • is there any property or event i need to set before i compile the code? – andrei Nov 07 '10 at 19:15
  • @andrei: Of course you need to set the `OnFormCreate` and `OnFormDestroy` events in the IDE, but otherwise, no, you do not need to set any property. (Just because there is a method named `FormCreate` in the code doesn't make this method execute when the form is created. You need to set the `OnCreate` event in the IDE to `FormCreate`, and similarly for the `OnDestroy` event.) – Andreas Rejbrand Nov 07 '10 at 19:20
  • it works now. but let's say i want to put a command on ctrl+2 on the same time. it's ok to use it like this? – andrei Nov 07 '10 at 19:44
  • Just register another hotkey, with a new ID, and check for both in response to `WM_HOTKEY` (using a `case` statement). – Andreas Rejbrand Nov 07 '10 at 19:47
2

to complement the Andreas answer you can use the RegisterHotKey function in combination with the WM_HOTKEY windows message.

try this code

type
  TForm17 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    HotKey1 : Integer;
    HotKey2 : Integer;
    procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
  public
    { Public declarations }
  end;

var
  Form17: TForm17;

implementation

{$R *.dfm}

{ TForm17 }

procedure TForm17.FormCreate(Sender: TObject);
const
  MOD_CONTROL = $0002;//0x0002
begin
  // Register Ctrl + 1 hotkey
  HotKey1 := GlobalAddAtom('Hotkey1');
  RegisterHotKey(Handle, HotKey1, MOD_CONTROL, Ord('1'));
  // Register  Ctrl + 2 hotkey
  HotKey2 := GlobalAddAtom('Hotkey2');
  RegisterHotKey(Handle, HotKey2, MOD_CONTROL, Ord('2'));
end;

procedure TForm17.FormDestroy(Sender: TObject);
begin
  //unregister the hotkeys
  UnRegisterHotKey(Handle, HotKey1);
  GlobalDeleteAtom(HotKey1);
  UnRegisterHotKey(Handle, HotKey2);
  GlobalDeleteAtom(HotKey2);
end;

procedure TForm17.WMHotKey(var Msg: TWMHotKey); 
begin
  if Msg.HotKey = HotKey1 then
  begin
    ShowMessage('Ctrl + 1 was pressed');
    //do your stuff
  end
  else
  if Msg.HotKey = HotKey2 then
  begin
    ShowMessage('Ctrl + 2 was pressed');
    //do your stuff
  end;
end;
RRUZ
  • 134,889
  • 20
  • 356
  • 483
1

As others suggested, it's RegisterHotKey function. However, proper implementation of the application that you want to design requires keyboard hook and DLL injection into the application.

I would recommend that you take a look at TypePilot application. It lets you type or copy/paste any text with certain shortcuts that you type. Eg. you can type "thnk " and this will be replaced with "thank you" by the application.

Eugene Mayevski 'Callback
  • 45,135
  • 8
  • 71
  • 121
  • Why? I think it could suffice to get the handle of the active window and send a paste message? – Remko Nov 07 '10 at 09:38
  • 1
    Paste message will paste clipboard contents. If you think you will replace clipboard contents with your text, paste your text and put data back to clipboard, think again: it's not necessary that clipboard actually contents data. It's possible to put a reference to the data to clipboard, and you won't be able to save it properly. – Eugene Mayevski 'Callback Nov 07 '10 at 16:52