C# winfrom 自动调整控件大小

最近公司要重构一个项目,把C++写的桌面应用改为winfrom,而此时我遇到一个问题就是winfrom控件的自动放大和缩小,就是根据窗口的大小来改变winfrom窗口和容器内的控件的大小。 在网上找了很多得到的效果并不如意,大多数都在介绍控件中的Anchor属性,但是这个属性会受各方面的影响,比如说容器,并不能达到自己想要的效果,后来在网上找到一段代码基本可以完成某些部分的放大和缩小,但是还是会出现一些问题:

  1. 当窗口最小化后重新打开窗口就会发生混乱
  2. 因为每个计算结果都是向上取整,也就是只要有小数点就会加一导致放大缩小后几次控件就会挤在一
  3. 如果将控件放在容器中就会发生混乱


为了解决这些问题,我对代码进行了部分修改如下所示:

注意!使用该类的时候每个控件的Anchor属性必须为None,AutoSize属性也必须为false,绝对不能设置MinimumSize和MaximumSize属性,否则窗口会在一定大小不再增大或缩小。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;



namespace MainWindows
{
    class AutoSizeFormClass
    {
        /// <summary>
        /// 声明结构 记录控件位置和大小
        /// </summary>
        public struct ControlRect
        {
            public string name;
            public float Left;
            public float Top;
            public float Width;
            public float Height;
            public float Size;
        }

        

        public List<ControlRect> _oldCtrl = new List<ControlRect>();
        private int _ctrlNo = 0;
        ControlRect decimals;

        public void RenewControlRect(Control mForm)
        {
            //如果控件集合对象_oldCtrl不存在则将其添加,如果不添加首先无法找到主窗口
            //也就无法开始遍历
            ControlRect cR;
            cR.name = mForm.Name;
            cR.Left = mForm.Left;
            cR.Top = mForm.Top;
            cR.Width = mForm.Width;
            cR.Height = mForm.Height;
            cR.Size = mForm.Font.Size;
            _oldCtrl.Add(cR);

            AddControl(mForm);
            

            _ctrlNo = 1;
        }
        

        private void AddControl(Control ctrl)
        {
            foreach (Control c in ctrl.Controls)
            {
                ControlRect cR;
                cR.name = c.Name;
                cR.Left = c.Left;
                cR.Top = c.Top;
                cR.Width = c.Width;
                cR.Height = c.Height;
                cR.Size = c.Font.Size;
                _oldCtrl.Add(cR);
                // 控件可能嵌套子控件
                if (c.Controls.Count > 0)
                    AddControl(c);
            }
        }

        public void ControlAutoSize(Control mForm)
        {      

            _ctrlNo = 1;
            /*计算宽度比率*/
            float wScale = (float)mForm.Width / _oldCtrl[0].Width;
            /*计算高度比率*/
            float hScale = (float)mForm.Height / _oldCtrl[0].Height;
            AutoScaleControl(mForm, wScale, hScale);
        }

        private void AutoScaleControl(Control mForm, float wScale, float hScale)
        {
            float ctrlLeft, ctrlTop, ctrlWidth, ctrlHeight;
            float ctrlFontSize, hSize, wSize;
            List<ControlRect> Ctrl = new List<ControlRect>();
            foreach (Control c in mForm.Controls)
            {
                //在_oldCtrl 中查询出控件名称相同的控件,并返回对象
                ControlRect shortDigits = _oldCtrl.Where((p) => p.name == c.Name).ToList().FirstOrDefault();

                
                //获取左边框的长度
               ctrlLeft = shortDigits.Left;
                //获取上边框的长度
               ctrlTop = shortDigits.Top;
                //获取宽度
               ctrlWidth = shortDigits.Width;
                //获取高度
               ctrlHeight = shortDigits.Height;
                //获取字体大小
               ctrlFontSize = shortDigits.Size;

                //通过获取的比率相乘计算出要显示的x,y轴
               c.Left = (int)Math.Round((ctrlLeft * wScale));
                if(c.Left< 0) {
                    c.Left = 0;
                }
                c.Top = (int)Math.Round((ctrlTop * hScale));
                if(c.Top < 0 ) {
                    c.Top = 0;
                }
                //保存计算结果后的坐标和大小,当下次进行计算是使用该浮点型进行计算
                //确保控件不会错乱
               
                

                //设置高度和宽度
                c.Width = (int)Math.Round((ctrlWidth * wScale));
                c.Height = (int)Math.Round((ctrlHeight * hScale));

                //通过比率获取放大或缩小后的字体大小并进行设置
                wSize = ctrlFontSize * wScale;
                hSize = ctrlFontSize * hScale;
                if (hSize < 7)
                {
                    hSize = 7;
                }
                if (wSize < 7)
                {
                    wSize = 7;
                }
                c.Font = new Font(c.Font.Name, Math.Min(hSize, wSize), c.Font.Style, c.Font.Unit);

                _ctrlNo++;

                // 先缩放控件本身 再缩放子控件
                if (c.Controls.Count > 0)
                {
                    AutoScaleControl(c, wScale, hScale);
                }

                shortDigits.Top = ctrlTop * hScale;
                shortDigits.Left = ctrlTop * wScale;
                shortDigits.Width = ctrlTop * wScale;
                shortDigits.Height = ctrlTop * hScale;
                //Ctrl.Add(shortDigits);
            }
            
        }
    }
}

 

调用方式

调用方式如下所示:

注意!一定要用如下格式或者类似如下格式进行调用,否则出现错误

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MainWindows
{
    public partial class Form1 : Form
    {
        AutoSizeFormClass asc = new AutoSizeFormClass();

        public Form1()
        {
            InitializeComponent();
            asc.RenewControlRect(this);
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            asc.ControlAutoSize(this);  
        }
        
    }
}

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值