WinForm窗体控件自适应大小

第一步:新建结构体,用于存储窗体属性
第二步:新建集合用于存储对应控件结构的属性
第三步:将控件的属性添加到集合中
第四步:计算出放大和缩小的比例
第五步:输出实际的控件大小
参考:https://blog.csdn.net/hy6688_/article/details/19431097

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

namespace _2DMotionPlatform.FormAutoSizi
{
    public class FormAutoSize
    {
        // 定义一个控件编号,初始化变量为0,表示窗体本身;后续的为各个控件的编号。
        int CtrNo = 0;
        // 声明一个泛型集合,类型为保存控件属性的结构体
        public List<ControlProperty> OrigenalControl = new List<ControlProperty>();

        // 声明一个结构体,用于保存控件的基本属性
        public struct ControlProperty
        {
            public int Left;
            public int Top;
            public int Width;
            public int Height;
            public float FontSize;
        }
        //收集控件的属性到集合中
        public void AddControlToList(Control control)
        {
            ControlProperty Ctp = new ControlProperty();    //新建一个控件属性结构体的实例
            foreach (Control c in control.Controls) {                   //遍历当前引入的控件集
                Ctp.Left = c.Left;
                Ctp.Top = c.Top;
                Ctp.Width = c.Width;
                Ctp.Height = c.Height;
                Ctp.FontSize = c.Font.Size;
                OrigenalControl.Add(Ctp);
                if (c.Controls.Count > 0) {
                    AddControlToList(c);                   //递归函数调用,防止遗漏嵌套的控件(如:Group、Panel等)
                }
            }
        }
        // 窗体自适应分辨率
        public void ControlAutoSize(Control MainForm) {
            
            if (CtrNo == 0) {
                ControlProperty Ctp = new ControlProperty();
                Ctp.Left = MainForm.Left;
                Ctp.Top = MainForm.Top;
                Ctp.Height = MainForm.Height;
                Ctp.Width = MainForm.Width;
                Ctp.FontSize = MainForm.Font.Size;
                //先把主窗体的属性加入到集合
                OrigenalControl.Add(Ctp);
                //添加辅窗体控件属性到集合
                AddControlToList(MainForm);
            }
            //求取分辨率的缩放比例
            float WidthScale = (float)MainForm.Width / (float)OrigenalControl[0].Width;
            float HightScale = (float)MainForm.Height / (float)OrigenalControl[0].Height;
            CtrNo = 1; ;//第0个为窗体本身,窗体内的控件,从序号1开始
            AutoScaleControl(MainForm, WidthScale, HightScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用
        }

        private void AutoScaleControl(Control mForm, float wScale, float hScale)
        {
            int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0;
            float ctrFontSize0;
            //第1个是窗体自身的 Left,Top,Width,Height,所以窗体控件从ctrlNo=1开始
            foreach (Control c in mForm.Controls)
            {
                //获得控件原有的位置和大小信息
                ctrLeft0 = OrigenalControl[CtrNo].Left;
                ctrTop0 = OrigenalControl[CtrNo].Top;
                ctrWidth0 = OrigenalControl[CtrNo].Width;
                ctrHeight0 = OrigenalControl[CtrNo].Height;
                ctrFontSize0 = OrigenalControl[CtrNo].FontSize;
                //设置控件新的位置和大小信息。
                c.Left = (int)((ctrLeft0) * wScale);//新旧控件之间的线性比例。控件位置只相对于窗体
                c.Top = (int)((ctrTop0) * hScale);//
                c.Width = (int)(ctrWidth0 * wScale);//只与最初的大小相关,所以不能与现在的宽度相乘 
                c.Height = (int)(ctrHeight0 * hScale);//
                c.Font = new Font(c.Font.Name, (float)(ctrFontSize0 * wScale));//设置控件中字体的大小以适应控件的大小
                CtrNo++;//累加序号
                //**放在这里,是先缩放控件本身,后缩放控件的子控件,重点是前后要一致(与保存时)
                if (c.Controls.Count > 0)
                    AutoScaleControl(c, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用
            }
            Debug.Write("如果对象是通过get()方法获取的,而不是new出来的,就可以通过在循环中改变对象的属性的方式来改变集合中该对象的属性值。");
        }
    }
}

实现窗体的自适应分辨率,只需要在窗体的Layout事件中添加如下代码:
        FormAutoSize formAutoSize = new FormAutoSize();
        private void Form1_Layout(object sender, LayoutEventArgs e)
        {
            formAutoSize.ControlAutoSize(this);
        }

注意:无论是通过foreach还是通过for循环遍历的时候,如果对象是通过get()方法获取的,而不是new出来的,就可以通过在循环中改变对象的属性的方式来改变集合中该对象的属性值。因为如果不是new出来的对象,该变量中存的只是从集合中传过来的一个存储真正对象的地址,并不会有这个变量自己的对象,当然也不会占用新的存储空间,当在循环中对该变量所进行的操作,都是对该变量所指向的对象进行的操作,因而会改变集合中对应对象的属性值。
参考代码下载地址:

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金增辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值