0

Possible Duplicate:
How can I handle a keyboard shortcut when my program isn't active?

hello guys i need to make a delphi program that creates a short cut key that works outside the delphi app. for example: when i press ctrl+1 it pastes a certain text. When i press ctrl+2, another text, and so on. It really helps my work. I managed to make a delphi application that does that, but it only works inside that app. i want it to work in all windows applications as long as my app is open ( and minimized). Can anyone help me out? I'm pretty new at delphi, i'm trying to learn.

I tried this code which someone recommended to me but it doesn't work. it does nothing. what did i do wrong?

unit Unit3;  

interface  

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

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');  
     Clipboard.AsText := 'This is my own text!';  

  end  
  else   
  if Msg.HotKey = HotKey2 then  
  begin  
    ShowMessage('Ctrl + 2 was pressed');  
     Clipboard.AsText := 'This is my own text!';  

  end;  
end;  

end.     
Community
  • 1
  • 1
andrei
  • 1
  • 1
  • Works here. Like Alberto says check the return of 'RegisterHotKey'. BTW, while you are posting a question you can select the code part and then click the 'Code Sample' button above the edit area. – Sertac Akyuz Nov 07 '10 at 14:55
  • you say u just paste the code and it works? outside the delphi app? in notepad or such? – andrei Nov 07 '10 at 15:01
  • i dont understand..if u guys know how to do it..why dont u just write the code down...so i can do something with it. i already told u i'm new at delphi, so as much as i appreciate your advices, it can;t help me much... :( – andrei Nov 07 '10 at 15:10
  • Sorry, I misread your code the first time. See my updated answer. – Alberto Martinez Nov 07 '10 at 15:48
  • 1
    Welcome to Stack Overflow. If an answer to a previous question didn't work, then please post a *comment* on that answer instead of re-posting the same question. But to post comments, you'll need to log in using the same account you used before. You can use the "contact us" link at the bottom of the page to ask a site administrator to merge your two accounts. – Rob Kennedy Nov 07 '10 at 16:26
  • @andrei: To do a thing like this, it is good to be familiar with the Windows API in addition to Delphi. – Andreas Rejbrand Nov 07 '10 at 17:24
  • @andrei: The code above, written by user RRUZ, simply puts the strings on clipboard (as you should be able to tell yourself). It doesn't send a paste message to the current control. My code (in my answer to your last identical question), however, does that. Did you try that? – Andreas Rejbrand Nov 07 '10 at 17:55
  • Andreas, my answer to this question http://stackoverflow.com/questions/4115429/how-can-i-handle-a-keyboard-shortcut-when-my-program-isnt-active, does not include the `Clipboard.AsText := 'This is my own text!'; ` part, this was written for the OP. – RRUZ Nov 07 '10 at 17:58
  • @RRUZ: Sorry. The OP really makes things confusing here... – Andreas Rejbrand Nov 07 '10 at 18:16

2 Answers2

2

You need to use RegisterHotKey and UnregisterHotKey from the Win32 API, they are very straightforward to use.

Also, you may find useful ShortCutToKey(), which returns the key code and shift state of a Delphi shortcut.

PS: Don't forget to check the return value of RegisterHotKey(), since it will fail if the hotkey is already registered by other application.

Edit: sorry, I though that you were using another WM_MESSAGE, since first you posted the code as plain text and I only scanned through it...

I think that the problem with your code is that your are using GlobalAddAtom for the ID key, but you only need to use an unique ID inside your app (the docs for the function say that you need to use GlobalAddAtom only for a shared DLL). Try using just this:

const
  ID_HOTKEY1=0;
  ID_HOTKEY2=1;

procedure TYourForm.FormCreate(Sender: TObject);
begin
  if not RegisterHotKey(Handle,ID_HOTKEY1,MOD_CONTROL,Ord('1'))
    then Application.MessageBox('Error registering hot key 1','Error',MB_ICONERROR);
  if not RegisterHotKey(Handle,ID_HOTKEY2,MOD_CONTROL,Ord('2'))
    then Application.MessageBox('Error registering hot key 2','Error',MB_ICONERROR);
end;

procedure TYourForm.FormDestroy(Sender: TObject);
begin
  UnregisterHotKey(Handle,ID_HOTKEY1);
  UnregisterHotKey(Handle,ID_HOTKEY2);
end;

procedure TYourForm.WMHotKey(var Msg: TWMHotKey);
begin
  Application.MessageBox(PChar(IntToStr(Msg.HotKey)),'Hotkey ID',MB_OK);
end;

Also, the MOD_CONTROL and related constants are already defined by Delphi, you don't need to redefine them.

Alberto Martinez
  • 2,620
  • 4
  • 25
  • 28
1

andrei, check this sample code to paste a text in a external application using a hotkey.

the code show two options

1) sending the Ctrl+V combination to the focused window

2) sending a WM_PASTE message

function GetFocusedHandle: THandle;
var
   ActiveHWND      : THandle;
   FocusedThread   : DWORD;
begin
  Result:=0;
  ActiveHWND    := GetForegroundWindow;
  FocusedThread := GetWindowThreadProcessID(ActiveHWND, nil) ;
  try
    if AttachThreadInput(GetCurrentThreadID, FocusedThread, true) then
      Result := GetFocus;
  finally
    AttachThreadInput(GetCurrentThreadID, FocusedThread, false) ;
  end;
end;

procedure TForm17.WMHotKey(var Msg: TWMHotKey);
var
  FocusWindowHwnd : THandle;
begin
  if Msg.HotKey = HotKey1 then //option 1
  begin
    Clipboard.AsText := 'Text from Ctrl + 1 Hotkey';//Assign the text to the clipboard
    //send the Ctrl + V combination to the current focused window
    keybd_event(VK_CONTROL, 0, 0, 0);
    keybd_event(Ord('V'), 0, 0, 0);
  end
  else
  if Msg.HotKey = HotKey2 then //option 2 
  begin
    FocusWindowHwnd:=GetFocusedHandle; //get the handle to the focused window
    if FocusWindowHwnd<>0 then
    begin
      Clipboard.AsText := 'Text from Ctrl + 2 Hotkey';//Assign the text to the clipboard
      SendMessage(FocusWindowHwnd,WM_PASTE,0,0);//send the WM_PASTE message 
    end;
  end;
end;
RRUZ
  • 134,889
  • 20
  • 356
  • 483