You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms C#使用clsResize类实现控件随窗体自动缩放时报错如何解决?

问题原因

你遇到的索引越界错误由以下几个常见原因导致:

  • 构造函数中订阅了Resize事件,该事件会在窗体Load事件执行前就触发,此时还未调用_get_initial_size方法存储控件初始尺寸,_arr_control_storage为空列表,访问索引时直接报错
  • 窗体最小化时ClientSize宽高为0,计算缩放比例时会出现无效值,后续设置控件尺寸时触发异常
  • 极端场景下两次递归获取控件的顺序或数量不一致,导致索引不匹配
修复方案

只需要修改clsResize类即可,不需要修改窗体侧的调用代码:

  1. 在_resize方法入口添加边界校验,避免未初始化、窗体最小化时执行缩放逻辑
  2. 索引访问前添加长度校验,避免越界
  3. 优化递归获取控件的逻辑,保证两次返回的控件顺序一致
完整修改后的clsResize代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;

public class clsResize
{
    List<Rectangle> _arr_control_storage = new List<Rectangle>();
    private bool showRowHeader = false;
    public clsResize(Form _form_)
    {
        form = _form_; 
        _formSize = _form_.ClientSize; 
        _fontsize = _form_.Font.Size; 
    }

    private float _fontsize  { get; set; }
    private SizeF _formSize {get;set; }
    private Form form { get; set; }

    public void _get_initial_size()
    {
        _arr_control_storage.Clear(); // 每次调用先清空旧数据
        var _controls = _get_all_controls(form).OrderBy(c=>c.Name).ToList(); // 按名称排序保证顺序固定
        foreach (Control control in _controls)
        {
            _arr_control_storage.Add(control.Bounds); 
            if (control is DataGridView dgv)
                _dgv_Column_Adjust(dgv, showRowHeader);
        }
    }

    public void _resize()
    {
        // 边界校验:未初始化、窗体最小化、初始尺寸无效时直接返回
        if (_arr_control_storage.Count == 0 
            || form.WindowState == FormWindowState.Minimized 
            || _formSize.Width <=0 || _formSize.Height <=0)
        {
            return;
        }
        
        double _form_ratio_width = (double)form.ClientSize.Width / (double)_formSize.Width;
        double _form_ratio_height = (double)form.ClientSize.Height / (double)_formSize.Height;
        var _controls = _get_all_controls(form).OrderBy(c=>c.Name).ToList(); // 同样按名称排序
        
        for(int _pos=0; _pos < _controls.Count && _pos < _arr_control_storage.Count; _pos++) // 用for循环替代,直接加长度校验
        {
            Control control = _controls[_pos];
            Size _controlSize = new Size(
                (int)(_arr_control_storage[_pos].Width * _form_ratio_width),
                (int)(_arr_control_storage[_pos].Height * _form_ratio_height)); 

            Point _controlposition = new Point(
                (int)(_arr_control_storage[_pos].X * _form_ratio_width),
                (int)(_arr_control_storage[_pos].Y * _form_ratio_height));

            control.Bounds = new Rectangle(_controlposition, _controlSize); 

            if (control is DataGridView dgv)
                _dgv_Column_Adjust(dgv, showRowHeader);

            // 字体大小计算增加最小最大值限制,避免字体过大或过小
            float newFontSize = (float)((_fontsize * _form_ratio_width + _fontsize * _form_ratio_height) / 2);
            newFontSize = Math.Max(6, Math.Min(72, newFontSize));
            control.Font = new Font(form.Font.FontFamily, newFontSize);
        }
    }

    private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader)
    {
        int intRowHeader = 0;
        const int Hscrollbarwidth = 5;
        if (_showRowHeader)
            intRowHeader = dgv.RowHeadersWidth;
        else
            dgv.RowHeadersVisible = false;

        if (dgv.ColumnCount == 0 || dgv.Width <= intRowHeader + Hscrollbarwidth) 
            return; // 列数为0或者宽度过小时直接返回
        
        for (int i = 0; i < dgv.ColumnCount; i++)
        {
            if (dgv.Dock == DockStyle.Fill)
                dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
            else
                dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
        }
    } 

    private static IEnumerable<Control> _get_all_controls(Control c)
    {
        return c.Controls.Cast<Control>()
            .SelectMany(item => _get_all_controls(item))
            .Concat(c.Controls.Cast<Control>())
            .Where(control => !string.IsNullOrEmpty(control.Name));
    }
}
可选优化(非必须)

如果有动态添加/删除控件的需求,在修改控件集合后重新调用一次_form_resize._get_initial_size()即可。

内容的提问来源于stack exchange,提问作者Bumba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 18:36:07