首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Windows Mobile / WinForms 介面自適應:動態控制項 DPI 縮放完整解決方案

     編輯:關於.NET

Windows Mobile / WinForms 開發中,設計器生成的控制項能自動適應螢幕 DPI,但運行時動態建立的控制項卻顯示極小。本文剖析 AutoScale 機制,提供在 ScaleControl 重寫中注入動態控制項的最佳實踐。

問題根因

  • 設計器在 InitializeComponent 結尾呼叫 ResumeLayout(false) → 觸發 PerformAutoScale() → ScaleControl() 縮放所有現有控制項。
  • 動態控制項在 InitializeComponent 之後 建立,錯過縮放時機,保持設計時像素大小,高 DPI 裝置上極小難讀。

AutoScale 核心屬性

this.AutoScaleDimensions = new SizeF(96F, 96F);  // 設計時 DPI (96 DPI 基準)
this.AutoScaleMode = AutoScaleMode.Dpi;          // 依 DPI 縮放
this.AutoScroll = true;                          // 內容超出自動捲動

執行時 CurrentAutoScaleDimensions 為實際 DPI,縮放因子 = 實際/設計時。

錯誤嘗試:建構函式中 Suspend/Resume

public Form1() {
  InitializeComponent();
  SuspendLayout();
  AutoScaleDimensions = new SizeF(96F, 96F); // 重設設計時基準
  GenerateControls();                        // 建立動態控制項
  PerformAutoScale();                        // 錯誤:設計器控制項被二次縮放!
  ResumeLayout(false);
}

PerformAutoScale 會對**所有**控制項(含已縮放的設計器控制項)再次縮放,導致疊加錯誤。

正確方案:重寫 ScaleControl 注入動態建立

縮放調用鏈:LayoutResume → PerformAutoScale → Scale → ScaleControl → ScaleChildControls。
在 基類 ScaleControl 執行前 建立動態控制項,使其參與本次縮放:

protected override void ScaleControl(SizeF factor, BoundsSpecified specified) {
  // 1. 先建立動態控制項(僅首次縮放時需建立)
  if (!controlsGenerated) {
    var categories = Config.Instance.Categories;
    GenerateCheckBoxes(categories);
    controlsGenerated = true;
  }
  // 2. 呼叫基類執行實際縮放(包含新建控制項)
  base.ScaleControl(factor, specified);
}

關鍵點:
- 僅在首次縮放(表單載入)時建立動態控制項。
- 後續 DPI 變更(極少見)會再次觸發 ScaleControl,但 controlsGenerated 防止重複建立。
- 基類 ScaleControl 會遞迴縮放 Controls 集合內所有子控制項。

運行期後續動態新增控制項

若遊戲運行中需新增控制項,不可再用 PerformAutoScale(會重複縮放舊控制項)。改為直接呼叫新控制項的 Scale(factor):

void AddDynamicControl(Control ctrl) {
  ctrl.Scale(this.AutoScaleFactor); // 手動套用當前縮放因子
  this.Controls.Add(ctrl);
}

跨平台驚喜

同一套 WinForms 程式碼,**無修改即可在 Windows 7 桌面正常運行**。WinForms 的 DPI 感知機制自動處理桌面與行動裝置差異,驗證了 .NET 跨平台 UI 一致性。

除錯痛點與建議

  • VS 模擬器 DPI 常與設計時一致,無法驗證縮放。**必須實機測試**。
  • 使用 Debug.WriteLine 輸出 AutoScaleFactor、控制項 Size 追蹤縮放過程。
  • 考慮改用 WPF(原生 DPI 獨立)或 .NET MAUI 進行新專案開發。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved