首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

DELPHI 自適應表單實現:螢幕解析度自動適配指南

     編輯:Delphi

問題背景

開發機解析度 (如 1920x1080) 與用戶機 (如 1366x768、800x600) 不一致時,固定像素佈局的表單會出現:控件超出螢幕、字體過大/過小、相對位置錯位等問題。本文提供兩種經典適配方案。

方案一:ScaleBy 縮放法 (主動適應)

核心思路:記錄設計時解析度,運行時按比例縮放表單及所有控件 (含字體)。

實現代碼

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 說明

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 感知),可實現真正的「一次設計、多解析度運行」。

總結建議

  1. 優先使用錨點/對齊/佈局管理器 實現流式佈局,根治解析度依賴。
  2. 舊專案快速移植:ScaleBy 縮放法最省力,接受字體模糊與相對位置固定。
  3. 全螢幕獨佔場景 (遊戲/終端) 可考慮 ChangeDisplaySettings,但需妥善處理異常恢複與多螢幕。
  4. 啟用 High-DPI 感知 (專案選項 → Application → Enable High-DPI) 並提供多解析度圖示資源。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved