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

C# WinForms 控制項隨視窗自動縮放佈局 (完整原始碼)

     編輯:關於C語言

實作視窗大小變更時,所有子控制項按比例縮放位置與大小,支援巢狀容器、最小尺寸保護與捲軸自動切換。核心思路:載入時記錄每個控制項的初始 `Location`、`Size` 及表單 `ClientSize`,`SizeChanged` 事件中依比例重新計算。

核心資料結構


class ControlLayoutInfo
{
    public Control Control;
    public Point InitialLocation;
    public Size InitialSize;
    public ControlLayoutInfo(Control c) { Control = c; InitialLocation = c.Location; InitialSize = c.Size; }
}

完整 Form 程式碼


public partial class AutoScaleForm : Form
{
    private readonly List _infos = new List();
    private Size _initialFormSize;
    private bool _initialized;

    public AutoScaleForm()
    {
        InitializeComponent();
        Load += (s, e) => InitializeLayout();
        SizeChanged += (s, e) => ApplyScale();
    }

    private void InitializeLayout()
    {
        _initialFormSize = ClientSize;
        CollectControls(this);
        _initialized = true;
    }

    private void CollectControls(Control container)
    {
        foreach (Control c in container.Controls)
        {
            _infos.Add(new ControlLayoutInfo(c));
            if (c.HasChildren) CollectControls(c); // 遞迴處理巢狀容器
        }
    }

    private void ApplyScale()
    {
        if (!_initialized || ClientSize.Width == 0 || ClientSize.Height == 0) return;

        double scaleX = (double)ClientSize.Width / _initialFormSize.Width;
        double scaleY = (double)ClientSize.Height / _initialFormSize.Height;

        // 縮小至低於初始尺寸 → 顯示捲軸、不再縮放控制項
        if (scaleX < 1 || scaleY < 1)
        {
            AutoScroll = true;
            AutoScrollMinSize = _initialFormSize;
            ResetToInitial();
            return;
        }

        AutoScroll = false;
        foreach (var info in _infos)
        {
            var c = info.Control;
            if (c.IsDisposed) continue;
            c.Location = new Point(
                (int)(info.InitialLocation.X * scaleX),
                (int)(info.InitialLocation.Y * scaleY)
            );
            c.Size = new Size(
                (int)(info.InitialSize.Width * scaleX),
                (int)(info.InitialSize.Height * scaleY)
            );
        }
    }

    private void ResetToInitial()
    {
        foreach (var info in _infos)
        {
            var c = info.Control;
            if (c.IsDisposed) continue;
            c.Location = info.InitialLocation;
            c.Size = info.InitialSize;
        }
    }
}

關鍵細節

  • 遞迴收集:`CollectControls` 遍歷所有巢狀容器 (`Panel`、`GroupBox`、`TabControl` 等) 內的控制項。
  • 最小尺寸保護:縮放比例 `< 1` 時改啟用 `AutoScroll`,避免控制項疊加/消失。
  • 效能:僅在 `SizeChanged` 計算佈局,無 Timer、無重繪迴圈。
  • 字體縮放:若需字體同步縮放,可在 `ApplyScale` 中額外設定 `c.Font = new Font(c.Font.FontFamily, c.Font.Size * (float)Math.Min(scaleX, scaleY))`。
  • 錨點/停靠衝突:此方案會覆蓋 `Anchor`/`Dock` 行為,兩者擇一使用。

替代方案比較

方案優點缺點
本文比例縮放像素級精確、支援任意佈局、無第三方依賴需手動管理、字體/圖片可能模糊
TableLayoutPanel / FlowLayoutPanel聲明式、自動重排、支援響應式像素級控制難、複雜佈局嵌套深
Anchor / Dock簡單、標準屬性僅邊緣固定、無法整體縮放
第三方 (DevExpress LayoutControl 等)功能豐富、設計器支援授權費、學習曲線

選擇方案取決於專案複雜度與維護團隊熟悉度。本文程式碼可直接複製到專案中繼承使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved