開發後台監控、記錄器或防竊軟體時,常需滿足三個條件:
本文示範在 Delphi 5/6/7 於 Windows 98 環境下,利用 RegisterServiceProcess 將進程偽裝為系統服務,並配合 RegisterHotKey 實現全域熱鍵喚醒。
const
RSP_SIMPLE_SERVICE = 1;
function RegisterServiceProcess(dwProcessID, dwType: DWORD): DWORD; stdcall;
external 'KERNEL32.DLL';
RegisterServiceProcess(GetCurrentProcessID, RSP_SIMPLE_SERVICE) 可將目前進程從工作管理員的應用程式清單移除(僅限 Windows 9x)。
procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;id := GlobalAddAtom('MyHotkey');RegisterHotKey(Handle, id, MOD_CONTROL + MOD_ALT, VK_R);WMHotKey 中判斷 Msg.HotKey = id 並顯示表單。UnregisterHotKey + GlobalDeleteAtom。unit Unit1;
interface
uses
Windows, Messages, Forms, Dialogs, Classes, Controls, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton; { 隱藏為服務 }
Button2: TButton; { 正常關閉 }
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
id: Integer; { 熱鍵 ID }
procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
public
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
const
RSP_SIMPLE_SERVICE = 1;
MOD_ALT = 1;
MOD_CONTROL = 2;
VK_R = 82;
function RegisterServiceProcess(dwProcessID, dwType: DWORD): DWORD; stdcall;
external 'KERNEL32.DLL';
{ 熱鍵訊息處理 }
procedure TForm1.WMHotKey(var Msg: TWMHotKey);
begin
if Msg.HotKey = id then
begin
ShowMessage('偵測到熱鍵 Ctrl+Alt+R 被按下!');
Form1.Visible := True; { 喚醒主視窗 }
Form1.WindowState := wsNormal; { 確保非最小化 }
Form1.BringToFront;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{ 防止多重啟動:檢查原子是否已存在 }
if GlobalFindAtom('MyHotkey') = 0 then
begin
id := GlobalAddAtom('MyHotkey');
RegisterHotKey(Handle, id, MOD_CONTROL + MOD_ALT, VK_R);
end
else
Halt; { 已有實例在跑,直接結束 }
end;
{ 註冊為系統服務並隱藏 }
procedure TForm1.Button1Click(Sender: TObject);
begin
RegisterServiceProcess(GetCurrentProcessId, RSP_SIMPLE_SERVICE);
Form1.Hide;
end;
{ 正常關閉程式 }
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;
{ 表單關閉時清理資源 }
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle, id);
GlobalDeleteAtom(id);
end;
end.
FormCreate 中以 GlobalFindAtom 檢查同名原子,若存在即 Halt,比 Mutex 更輕量(但僅限同 Session)。RegisterHotKey 會失敗(回傳 False),建議改用較罕見組合(如 Ctrl+Alt+Shift+F12)。RegisterServiceProcess 僅在 Windows 95/98/Me 有效。NT 核心系統請改用真正的 Windows Service(CreateService + StartServiceCtrlDispatcher)或將主視窗 Visible := False、ShowInTaskBar := stNever、SetWindowLong(Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW) 隱藏工作列圖示。requireAdministrator。{ 隱藏工作列圖示 }
Application.ShowMainForm := False;
Form1.ShowInTaskBar := stNever;
SetWindowLong(Form1.Handle, GWL_EXSTYLE,
GetWindowLong(Form1.Handle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
{ 真正的 Windows Service 專案範本 }
{ File > New > Other > Service Application }
雖然 RegisterServiceProcess 已成歷史,但「全域熱鍵 + 隱藏主視窗」的架構思維在現代 Delphi 開發中依然通用。掌握 WM_HOTKEY、GlobalAddAtom、RegisterHotKey 的協作流程,能為各類常駐後台工具(截圖、翻譯、剪貼簿增強、快捷啟動器)提供堅實基礎。