開發機解析度 (如 1920x1080) 與用戶機 (如 1366x768、800x600) 不一致時,固定像素佈局的表單會出現:控件超出螢幕、字體過大/過小、相對位置錯位等問題。本文提供兩種經典適配方案。
核心思路:記錄設計時解析度,運行時按比例縮放表單及所有控件 (含字體)。
const
DesignWidth = 1024; // 設計時螢幕寬度
DesignHeight = 768; // 設計時螢幕高度
procedure TForm1.FormCreate(Sender: TObject);
begin
Scaled := True; // 允許縮放 (預設 True)
if (Screen.Width <> DesignWidth) or (Screen.Height <> DesignHeight) then
begin
// 先調整表單自身尺寸
Width := MulDiv(Width, Screen.Width, DesignWidth);
Height := MulDiv(Height, Screen.Height, DesignHeight);
// 再縮放內部控件 (含字體)
ScaleBy(Screen.Width, DesignWidth);
end;
end;
Scaled := True:啟用 VCL 內建縮放機制 (預設開啟)。MulDiv:整數乘除避免溢位,等同 Width * Screen.Width div DesignWidth 但更安全。ScaleBy:遞歸縮放表單及所有子控件的 Left, Top, Width, Height, Font.Size。ScaleBy 不改變控件間相對位置 (Left/Top 也按比例縮放),若設計時留白不足,縮放後可能擁擠;無法實現「流式佈局」或「響應式換行」。核心思路:程式啟動時強制將系統螢幕解析度切換為設計時解析度,退出時恢復。
uses ..., Registry; // 需 Registry 單元讀取當前模式
procedure TForm1.FormCreate(Sender: TObject);
var DevMode: TDeviceMode;
begin
if (Screen.Width <> DesignWidth) or (Screen.Height <> DesignHeight) then
begin
// 獲取當前顯示設備模式
if EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, DevMode) then
begin
DevMode.dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
DevMode.dmPelsWidth := DesignWidth;
DevMode.dmPelsHeight := DesignHeight;
// CDS_FULLSCREEN 模式不永久更改註冊表,登出/重啟自動恢復
if ChangeDisplaySettings(DevMode, CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL then
ShowMessage('無法切換解析度,將以當前解析度運行');
end;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// 程式結束時恢復原解析度 (ChangeDisplaySettings(nil, 0) 或 CDS_RESET)
ChangeDisplaySettings(nil, 0);
end;
| API | 用途 | 關鍵參數 |
|---|---|---|
| EnumDisplaySettings | 獲取/枚舉顯示模式 | lpszDeviceName=nil (主顯示器), iModeNum=ENUM_CURRENT_SETTINGS |
| ChangeDisplaySettings | 更改解析度/刷新率/色深 | lpDevMode 指向 TDeviceMode, dwFlags=CDS_FULLSCREEN (臨時) 或 0 (永久) |
| 維度 | ScaleBy 縮放法 | ChangeDisplaySettings 法 |
|---|---|---|
| 用戶體驗 | 無感,應用內部適配 | 全螢幕閃爍,影響其他應用 |
| 多螢幕支援 | 良好 (各自縮放) | 困難 (通常只改主螢幕) |
| 權限需求 | 無 | 需使用者同意/管理員權限 |
| 字體清晰度 | 縮放後可能模糊 (非整數倍) | 原生解析度最銳利 |
| 適用場景 | 一般商務應用、多解析度部署 | 全螢幕遊戲、專用終端機、Kiosk 模式 |
Delphi 10.4+ 強烈建議使用 FireMonkey (FMX) 或 VCL 新增的佈局管理器:
TFlowLayout / TGridLayout:自動換行/對齊TAnchor (akLeft, akRight, akTop, akBottom):錨定邊緣TAlign (alClient, alTop, alBottom, alLeft, alRight, alCustom):填充/停靠TControl.Margins / Padding:內外邊距OnResize 事件手動微調複雜佈局配合 Scaled := True 且設計時基準 96 DPI (或啟用 High-DPI 感知),可實現真正的「一次設計、多解析度運行」。
ScaleBy 縮放法最省力,接受字體模糊與相對位置固定。ChangeDisplaySettings,但需妥善處理異常恢複與多螢幕。