Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This does what you want.</p> <p>First, you need a program that runs in the background and listens to, and responds to, keystrokes. Like this:</p> <pre><code>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)) &lt;&gt; 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. </code></pre> <p>(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 <code>Application.Initialize</code> nonsense. The program should look like the above.)</p> <p>The above program listens to the messages <code>WM_SETHOTKEY</code> that registers a new Windows hotkey, <code>WM_UNSETHOTKEY</code> that removes a previously registered hotkey, and <code>WM_HOTKEY</code> 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.</p> <p>To register a hotkey, send the message <code>WM_SETHOTKEY</code> to the window <code>W</code>. The <code>wParam</code> of the message should be the index (in the <code>FileNames</code> array) of the program to start. The <code>lParam</code> should be of the form $MMMMKKKK where $MMMM are the modifiers (<kbd>Ctrl</kbd>, <kbd>Alt</kbd>, <kbd>Shift</kbd>) and $KKKK the virtual-key code of the hotkey. To remove a hotkey, send a <code>WM_UNSETHOTKEY</code> message with the program index as <code>wParam</code> to <code>W</code>.</p> <h1>Sample usage</h1> <p>From <em>any</em> application, you can do (assuming that Project1.exe is running in the background)</p> <pre><code>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; </code></pre> <p>Now, even if you close this new program, notepad.exe and pbrush.exe will start on <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>N</kbd> and <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>P</kbd>, respectively.</p> <h1>Some more discussion</h1> <p>Notice that, when compiled, Project1.exe is only 20 kB small! This is <em>tiny</em> for an application made in Delphi!</p> <p>To unregister a previously registered hotkey, do</p> <pre><code>PostMessage(w, WM_UNSETHOTKEY, N, 0); </code></pre> <p>where N, in this example, is = 0 for notepad and = 1 for pbrush.</p> <p>To quit project1.exe, do</p> <pre><code>PostMessage(w, WM_QUIT, 0, 0); </code></pre> <p>But, of course, if you quit project1.exe, all hotkeys are unregistered by Windows.</p> <p>You might want to do</p> <pre><code>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; </code></pre> <p>or even start project1.exe if you cannot find the window.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload