This does what you want.
First, you need a program that runs in the background and listens to, and responds to, keystrokes. Like this:
program Project1;
uses
Windows, Messages, ShellAPI;
var
W: HWND;
M: MSG;
const
WM_SETHOTKEY = WM_APP + 1;
WM_UNSETHOTKEY = WM_APP + 2;
AppName = 'Rejbrand Hot Key Listener';
const
FileNames: array[0..1] of string = ('notepad.exe', 'pbrush.exe');
begin
if FindWindow('STATIC', PChar(AppName)) <> 0 then
Exit;
W := CreateWindow('STATIC', PChar(AppName), 0, 0, 0, 100, 100, HWND_MESSAGE, 0, HInstance, nil);
while GetMessage(M, W, 0, 0) do
case M.message of
WM_HOTKEY:
ShellExecute(0, nil, PChar(FileNames[M.wParam]), nil, nil, SW_SHOWNORMAL);
WM_SETHOTKEY:
RegisterHotKey(W, M.wParam, M.lParam shr 16, M.lParam and $FFFF);
WM_UNSETHOTKEY:
UnregisterHotKey(W, M.wParam);
end;
end.
(To create this program, select New/VCL Forms Application, and then remove the main form from the project. Then select Project/View Source and remove the Application.Initialize
nonsense. The program should look like the above.)
The above program listens to the messages WM_SETHOTKEY
that registers a new Windows hotkey, WM_UNSETHOTKEY
that removes a previously registered hotkey, and WM_HOTKEY
that is sent by Windows when a registered hotkey is activated by the end-user. The first two messages are defined by me, in this application.
To register a hotkey, send the message WM_SETHOTKEY
to the window W
. The wParam
of the message should be the index (in the FileNames
array) of the program to start. The lParam
should be of the form $MMMMKKKK where $MMMM are the modifiers (Ctrl, Alt, Shift) and $KKKK the virtual-key code of the hotkey. To remove a hotkey, send a WM_UNSETHOTKEY
message with the program index as wParam
to W
.
Sample usage
From any application, you can do (assuming that Project1.exe is running in the background)
const
WM_SETHOTKEY = WM_APP + 1;
WM_UNSETHOTKEY = WM_APP + 2;
const
MODIFIER_ALT = MOD_ALT shl 16;
MODIFIER_CTRL = MOD_CONTROL shl 16;
MODIFIER_SHIFT = MOD_SHIFT shl 16;
procedure TForm1.RegisterHotkeys;
var
w: HWND;
begin
w := FindWindow('STATIC', 'Rejbrand Hot Key Listener');
PostMessage(w, WM_UNSETHOTKEY, 0, MODIFIER_CTRL + MODIFIER_ALT + ord('N'));
PostMessage(w, WM_SETHOTKEY, 1, MODIFIER_CTRL + MODIFIER_ALT + ord('P'));
end;
Now, even if you close this new program, notepad.exe and pbrush.exe will start on Ctrl + Alt + N and Ctrl + Alt + P, respectively.
Some more discussion
Notice that, when compiled, Project1.exe is only 20 kB small! This is tiny for an application made in Delphi!
To unregister a previously registered hotkey, do
PostMessage(w, WM_UNSETHOTKEY, N, 0);
where N, in this example, is = 0 for notepad and = 1 for pbrush.
To quit project1.exe, do
PostMessage(w, WM_QUIT, 0, 0);
But, of course, if you quit project1.exe, all hotkeys are unregistered by Windows.
You might want to do
procedure TForm1.RegisterHotkeys;
var
w: HWND;
begin
w := FindWindow('STATIC', 'Rejbrand Hot Key Listener');
if w = 0 then
MessageBox('Error: Rejbrand Hot Key Listener not running!');
PostMessage(w, WM_UNSETHOTKEY, 0, MODIFIER_CTRL + MODIFIER_ALT + ord('N'));
PostMessage(w, WM_SETHOTKEY, 1, MODIFIER_CTRL + MODIFIER_ALT + ord('P'));
end;
or even start project1.exe if you cannot find the window.