Delphi 作為經典的 Windows 開發工具,擁有豐富的 VCL 元件與 Windows API 呼叫能力。本文彙整 13 個常見開發場景的實用技巧,涵蓋鍵盤狀態檢測、系統熱鍵屏蔽、任務列控制、開機自啟動、StringGrid 動態著色、Memo 撤銷操作、目錄重命名、系統關機/重啟、磁碟變更偵測、錯誤模式設定、臨時路徑取得、檔案關聯開啟、磁碟機類型與容量查詢等,助你快速解決實際開發問題。
透過 Windows API GetKeyboardState 取得鍵盤狀態陣列,利用 Odd 函數判斷最低位是否為 1(表示開啟)。下例使用 Timer 週期性更新狀態列:
procedure TForm1.Timer1Timer(Sender: TObject);
var
ks: TKeyboardState;
begin
GetKeyboardState(ks);
StatusBar1.Panels[0].Text := IfThen(Odd(ks[VK_NUMLOCK]), 'NUM', '');
StatusBar1.Panels[1].Text := IfThen(Odd(ks[VK_INSERT]), 'INSERT', '');
StatusBar1.Panels[2].Text := IfThen(Odd(ks[VK_CAPITAL]), 'CAPITAL', '');
StatusBar1.Panels[3].Text := IfThen(Odd(ks[VK_SCROLL]), 'SCROLL', '');
end;
常數對照:VK_INSERT、VK_NUMLOCK、VK_CAPITAL、VK_SCROLL。
呼叫 SystemParametersInfo 並設定 SPI_SETFASTTASKSWITCH 與 SPI_SCREENSAVERRUNNING 即可禁用;恢復時將 Flag 設為 0。
procedure TForm1.FormCreate(Sender: TObject);
var
tmp: Integer;
begin
tmp := 0;
// 禁用 Alt+Tab
SystemParametersInfo(SPI_SETFASTTASKSWITCH, 1, @tmp, 0);
// 禁用 Ctrl+Alt+Del
SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, @tmp, 0);
end;
procedure TForm1.RestoreHotkeys;
var
tmp: Integer;
begin
tmp := 0;
SystemParametersInfo(SPI_SCREENSAVERRUNNING, 0, @tmp, 0);
end;
注意: 此操作需管理員權限,且僅適用於舊版 Windows(如 9x/2000/XP),現代 Windows 系統出於安全考量已限制此類行為。
尋找類別名為 Shell_TrayWnd 的視窗句柄,發送 SW_HIDE 或 SW_RESTORE 訊息。
procedure HideTaskbar;
var
wndHandle: THandle;
wndClass: array[0..50] of Char;
begin
StrPCopy(wndClass, 'Shell_TrayWnd');
wndHandle := FindWindow(wndClass, nil);
ShowWindow(wndHandle, SW_HIDE);
end;
procedure ShowTaskbar;
var
wndHandle: THandle;
wndClass: array[0..50] of Char;
begin
StrPCopy(wndClass, 'Shell_TrayWnd');
wndHandle := FindWindow(wndClass, nil);
ShowWindow(wndHandle, SW_RESTORE);
end;
向登錄機碼 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run 寫入程式路徑。
uses Registry;
procedure AddToStartup(const AppName, ExePath: string);
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Run', True) then
Reg.WriteString(AppName, ExePath);
finally
Reg.Free;
end;
end;
在 OnDrawColumnCell 事件中依資料值設定畫布字型顏色,再呼叫 DefaultDrawColumnCell 繪製。
procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if Table1.FieldByName('Population').AsInteger > 2000000 then
StringGrid1.Canvas.Font.Color := clBlue;
StringGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
程式碼控制撤銷與選單啟用狀態:
// 執行撤銷
Memo1.Perform(EM_UNDO, 0, 0);
// 判斷是否可撤銷,啟用選單項
Undo1.Enabled := Memo1.Perform(EM_CANUNDO, 0, 0) <> 0;
直接呼叫 RenameFile(同樣適用於目錄):
RenameFile('C:\Wang\Temp', 'C:\Wang\Tmp');
使用 ExitWindowsEx API,常數定義如下:
const
EWX_LOGOFF = 0; // 登出
EWX_SHUTDOWN = 1; // 關機
EWX_REBOOT = 2; // 重啟
EWX_FORCE = 4; // 強制關閉應用程式
// 範例:關機
ExitWindowsEx(EWX_SHUTDOWN or EWX_FORCE, 0);
比對磁碟機的 Volume Serial Number 即可判斷媒體是否更換。
function GetDiskVolSerialID(cDriveName: Char): DWORD;
var
dwTemp1, dwTemp2: DWORD;
begin
GetVolumeInformation(PChar(cDriveName + ':\'), nil, 0, Result, dwTemp1, dwTemp2, nil, 0);
end;
設定錯誤模式為 SEM_FAILCRITICALERRORS,讓關鍵錯誤直接回傳失敗而不彈出對話框。
var
OldErrorMode: UINT;
begin
OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
// 可能產生嚴重錯誤的程式碼
finally
SetErrorMode(OldErrorMode);
end;
end;
var
TempPath: array[0..MAX_PATH] of Char;
begin
GetTempPath(MAX_PATH, TempPath);
Edit1.Text := TempPath;
end;
呼叫 ShellExecute,系統會依副檔名或協定自動啟動對應程式。
procedure OpenURLorFile(const URL: string);
begin
ShellExecute(0, nil, PChar(URL), nil, nil, SW_SHOWNORMAL);
end;
// 使用範例
OpenURLorFile('Readme.txt');
OpenURLorFile('https://www.example.com');
類型判斷: GetDriveType 回傳 DRIVE_REMOVABLE(2)、DRIVE_FIXED(3)、DRIVE_REMOTE(4)、DRIVE_CDROM(5)、DRIVE_RAMDISK(6)。
容量查詢: GetDiskFreeSpace 取得扇區、叢集資訊,換算總容量與可用空間。
var
Driver: PChar;
SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters: DWORD;
TotalBytes, FreeBytes: Int64;
begin
Driver := 'C:\';
GetDiskFreeSpace(Driver, SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters);
TotalBytes := Int64(TotalClusters) * SectorsPerCluster * BytesPerSector;
FreeBytes := Int64(FreeClusters) * SectorsPerCluster * BytesPerSector;
Label1.Caption := Format('總容量: %.2f GB', [TotalBytes / 1024 / 1024 / 1024]);
Label2.Caption := Format('可用空間: %.2f GB', [FreeBytes / 1024 / 1024 / 1024]);
end;
以上技巧皆為 Delphi 開發中高頻需求,熟練掌握可大幅提升開發效率。實際專案中請注意版本相容性與權限需求,並妥善處理例外情況。