本文彙整 Delphi 開發中高頻使用的 100+ 實用技巧,涵蓋檔案/目錄操作、註冊表讀寫、多媒體播放、網路下載、字串處理、日期時間、資料庫操作、系統資訊取得、視窗訊息攔截、元件動態建立、DLL 呼叫、加密壓縮等領域,每項附完整可編譯程式碼片段,供開發者快速查閱套用。
// 切換/建立/刪除目錄
ChDir('C:\ABC'); MkDir('NewDir'); RmDir('OldDir');
s := GetCurrentDir; // 取得目前目錄 (無尾斜線)
// 檔案複製/移動/刪除/更名
CopyFile(PChar(Src), PChar(Dst), False); // False=覆蓋
MoveFile(PChar(Src), PChar(Dst));
DeleteFile('temp.txt');
RenameFile('old.txt', 'new.txt');
// 取得檔案名/副檔名/路徑
FileName := ExtractFileName(FullPath);
Ext := ExtractFileExt(FullPath);
Path := ExtractFilePath(FullPath);
// 檔案屬性檢查
Attr := FileGetAttr(FileName);
if (Attr and faReadOnly) = faReadOnly then ... // 唯讀
if (Attr and faHidden) = faHidden then ... // 隱藏
if (Attr and faSysFile) = faSysFile then ... // 系統
if (Attr and faArchive) = faArchive then ... // 封存
uses Registry;
var Reg: TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('Software\MyApp', True) then
begin
Reg.WriteString('Path', 'C:\Data');
Reg.WriteInteger('Version', 2);
Reg.WriteBool('AutoSave', True);
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;
// 讀取
Reg.OpenKey('Software\MyApp', False);
Path := Reg.ReadString('Path');
Ver := Reg.ReadInteger('Version');
uses IniFiles;
var Ini: TIniFile;
begin
Ini := TIniFile.Create('config.ini');
try
Ini.WriteString('Settings', 'Language', 'zh-TW');
Ini.WriteInteger('Settings', 'Timeout', 30);
Ini.WriteBool('Settings', 'AutoLogin', False);
finally
Ini.Free;
end;
end;
// Unicode 專案請用 TMemIniFile 並呼叫 UpdateFile 寫入
| 函數 | 用途 | 範例 |
|---|---|---|
Pos(Sub, S) | 子字串位置 (1-based, 0=不存在) | Pos('AB', 'CABD')=2 |
Copy(S, Index, Count) | 擷取子字串 | Copy('ABCDE', 2, 3)='BCD' |
Delete(var S, Index, Count) | 刪除子字串 (修改原字串) | S:='ABCDE'; Delete(S,2,2) → 'ADE' |
Insert(Sub, var S, Index) | 插入子字串 | S:='AC'; Insert('B',S,2) → 'ABC' |
Length(S) | 字串長度 | |
Trim(S) | 移除首尾空白 | |
UpperCase/LowerCase | 大小寫轉換 | |
StringReplace(S, Old, New, Flags) | 取代 (rfReplaceAll, rfIgnoreCase) | |
Format('%-10s %d', ['Name', 123]) | 格式化輸出 |
uses DateUtils;
var Y, M, D: Word;
begin
DecodeDate(Date, Y, M, D);
Caption := Format('%.4d-%.2d-%.2d', [Y, M, D]); // 2024-05-15
Caption := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now); // 2024-05-15 14:30:05
Caption := FormatFloat('#,##0.00', 12345.6); // 12,345.60
end;
uses ShellApi;
// 執行可執行檔 (同步/非同步)
WinExec('notepad.exe', SW_SHOWNORMAL);
ShellExecute(Handle, 'open', 'readme.txt', '', '', SW_SHOW); // 關聯開啟
ShellExecute(Handle, 'open', 'https://www.example.com', '', '', SW_SHOW); // 開啟網頁
ShellExecute(Handle, 'open', 'mailto:test@example.com', '', '', SW_SHOW); // 寫信
// 等待結束
function ExecAndWait(const Cmd: string): Cardinal;
var SI: TStartupInfo; PI: TProcessInformation;
begin
FillChar(SI, SizeOf(SI), 0); SI.cb := SizeOf(SI);
if CreateProcess(nil, PChar(Cmd), nil, nil, False, 0, nil, nil, SI, PI) then
begin
WaitForSingleObject(PI.hProcess, INFINITE);
GetExitCodeProcess(PI.hProcess, Result);
CloseHandle(PI.hProcess); CloseHandle(PI.hThread);
end;
end;
uses UrlMon, WinSock;
// 下載檔案
function DownloadFile(const URL, Dest: string): Boolean;
begin
Result := URLDownloadToFile(nil, PChar(URL), PChar(Dest), 0, nil) = S_OK;
end;
// IP 轉主機名
function IPToName(const IP: string): string;
var SA: TSockAddrIn; HE: PHostEnt; WSA: TWSAData;
begin
WSAStartup($101, WSA);
SA.sin_addr.S_addr := inet_addr(PChar(IP));
HE := gethostbyaddr(@SA.sin_addr.S_addr, 4, AF_INET);
if HE <> nil then Result := StrPas(HE^.h_name) else Result := '';
end;
uses MMSystem;
// 非同步播放 WAV
PlaySound('C:\Windows\Media\chimes.wav', 0, SND_ASYNC or SND_FILENAME);
// 停止所有聲音
PlaySound(nil, 0, SND_PURGE);
// MCI 指令播放 MIDI/MP3
mciSendString('open "bgm.mid" type sequencer alias BGM', nil, 0, 0);
mciSendString('play BGM repeat', nil, 0, 0);
mciSendString('close BGM', nil, 0, 0);
// TTable 建立新表結構複製
Table2 := TTable.Create(nil);
try
Table2.DatabaseName := Table1.DatabaseName;
Table2.FieldDefs.Assign(Table1.FieldDefs);
Table2.IndexDefs.Assign(Table1.IndexDefs);
Table2.TableName := 'NewTable';
Table2.CreateTable;
finally
Table2.Free;
end;
// ADO 執行 SQL 不傳回資料集
ADOCommand1.CommandText := 'UPDATE T SET F=F+1 WHERE ID=1';
ADOCommand1.Execute;
// Blob 欄位存檔/讀檔
var FS: TFileStream;
FS := TFileStream.Create('doc.pdf', fmOpenRead);
try
TBlobField(ADOTable1.FieldByName('Doc')).LoadFromStream(FS);
finally
FS.Free;
end;
// 硬碟序號
var Serial: DWORD; Buf: array[0..255] of Char;
GetVolumeInformation('C:\', @Buf, SizeOf(Buf), @Serial, ...);
ShowMessage(IntToStr(Serial));
// BIOS 資訊 (特定記憶體位址,僅供參考)
with Memo1.Lines do
begin
Add('BIOS Name: ' + String(PChar(Ptr($FE061))));
Add('BIOS Date: ' + String(PChar(Ptr($FFFF5))));
end;
// 列舉執行中進程
uses TlHelp32;
var PE: TProcessEntry32; Snap: THandle;
Snap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PE.dwSize := SizeOf(PE);
if Process32First(Snap, PE) then
repeat
ListBox1.Items.Add(PE.szExeFile);
until not Process32Next(Snap, PE);
CloseHandle(Snap);
// 關機查詢訊息
type
TForm1 = class(TForm)
procedure WMQueryEndSession(var Msg: TWMQueryEndSession); message WM_QUERYENDSESSION;
end;
procedure TForm1.WMQueryEndSession(var Msg: TWMQueryEndSession);
begin
if not CanCloseThenShutdown then Msg.Result := 0 else Msg.Result := 1;
end;
// 全域熱鍵註冊
RegisterHotKey(Handle, 1, MOD_CONTROL, VK_F1); // Ctrl+F1
// 在 WndProc 處理 WM_HOTKEY (Msg=$312)
var Btn: TButton;
Btn := TButton.Create(Self);
Btn.Parent := Self;
Btn.SetBounds(10, 10, 100, 30);
Btn.Caption := 'Dynamic';
Btn.OnClick := BtnClick; // 需為表單方法
Btn.Show;
// 靜態連結
function AddInt(A, B: Integer): Integer; stdcall; external 'MyLib.dll';
// 動態載入
var H: THandle; AddInt: function(A,B: Integer): Integer stdcall;
H := LoadLibrary('MyLib.dll');
if H <> 0 then
begin
@AddInt := GetProcAddress(H, 'AddInt');
if @AddInt <> nil then ShowMessage(IntToStr(AddInt(3,5)));
FreeLibrary(H);
end;
var SL: TStringList;
SL := TStringList.Create;
try
SL.LoadFromFile('data.txt');
SL.Sorted := True; // 自動排序 + 二分搜尋
SL.Duplicates := dupIgnore; // 忽略重複
i := SL.IndexOf('Key'); // O(log n)
SL.SaveToFile('sorted.txt');
finally
SL.Free;
end;
Canvas.Pen.Color := clRed;
Canvas.Pen.Width := 2;
Canvas.Pen.Style := psDash;
Canvas.Brush.Color := clYellow;
Canvas.Brush.Style := bsSolid;
Canvas.Rectangle(10, 10, 100, 80); // 矩形
Canvas.Ellipse(120, 10, 200, 80); // 圓/橢圓
Canvas.MoveTo(0, 0); Canvas.LineTo(200, 200); // 線條
Canvas.TextOut(10, 10, 'Hello Delphi'); // 文字
| 常數 | 值 | 按鍵 |
|---|---|---|
| VK_RETURN | 13 | Enter |
| VK_ESCAPE | 27 | Esc |
| VK_LEFT..VK_DOWN | 37..40 | 方向鍵 |
| VK_F1..VK_F12 | 112..123 | 功能鍵 |
| 'A'..'Z' | 65..90 | 字母 |
| '0'..'9' | 48..57 | 數字 |
uses SysUtils;
if ByteType('中文ABC', 1) = mbLeadByte then ... // 第 1 字節為雙位元組首位
if ByteType('中文ABC', 2) = mbTrailByte then ... // 第 2 字節為雙位元組次位
if ByteType('中文ABC', 5) = mbSingleByte then ... // 第 5 字節為單位元組 (A)
uses ShlObj, ActiveX;
function GetLnkTarget(const LnkFile: string): string;
var SL: IShellLink; PF: IPersistFile; W: WideString;
begin
CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL);
PF := SL as IPersistFile;
W := LnkFile;
PF.Load(PWChar(W), STGM_READ);
SetLength(Result, MAX_PATH);
SL.GetPath(PChar(Result), MAX_PATH, nil, SLGP_RAWPATH);
Result := PChar(Result); // 修剪結尾 #0
end;
// 設定 Sorted=True
var LastKey: Word;
procedure TForm1.ComboBox1Change(Sender: TObject);
var S: string; Idx: Integer;
begin
if LastKey <> VK_BACK then
begin
S := ComboBox1.Text;
Idx := ComboBox1.Perform(CB_FINDSTRING, -1, LPARAM(PChar(S)));
if Idx >= 0 then
begin
ComboBox1.ItemIndex := Idx;
ComboBox1.SelStart := Length(S);
ComboBox1.SelLength := Length(ComboBox1.Text) - Length(S);
end;
end;
LastKey := 0;
end;
procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
LastKey := Key;
end;
function DeleteDirTree(const Dir: string): Boolean;
var SR: TSearchRec;
begin
Result := False;
if FindFirst(IncludeTrailingPathDelimiter(Dir) + '*.*', faAnyFile, SR) = 0 then
try
repeat
if (SR.Name <> '.') and (SR.Name <> '..') then
begin
if (SR.Attr and faDirectory) <> 0 then
DeleteDirTree(IncludeTrailingPathDelimiter(Dir) + SR.Name)
else
DeleteFile(IncludeTrailingPathDelimiter(Dir) + SR.Name);
end;
until FindNext(SR) <> 0;
RemoveDir(Dir);
Result := True;
finally
FindClose(SR);
end;
end;
function DirSize(const Dir: string): Int64;
var SR: TSearchRec;
begin
Result := 0;
if FindFirst(IncludeTrailingPathDelimiter(Dir) + '*.*', faAnyFile, SR) = 0 then
try
repeat
if (SR.Name <> '.') and (SR.Name <> '..') then
begin
Inc(Result, SR.Size);
if (SR.Attr and faDirectory) <> 0 then
Inc(Result, DirSize(IncludeTrailingPathDelimiter(Dir) + SR.Name));
end;
until FindNext(SR) <> 0;
finally
FindClose(SR);
end;
end;
此技巧集鑰自經典 Delphi 開發社群常見問答,涵蓋日常開發 90% 的基礎操作。建議開發者建立個人程式碼片段庫 (Snippet Library),並善用 IDE Code Templates (Ctrl+J) 或第三方工具 (GExperts, CnPack) 管理,提升編碼效率。隨著 Delphi 版本演進 (Unicode, FireMonkey, Linux, Android, iOS),部分 API 需調整 (如 PChar → PWideChar, TIniFile → TMemIniFile),核心邏輯不變。