WinForm窗体及其控件自适应各种屏幕分辨率

@bruce  October 22, 2019

背景

我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观。实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比例变化即可。(因为窗体上控件的位置和大小是相对于自己所在的窗体的。)

使用方法

  • 声明自适应辅助类实例
  • 为窗体添加Load事件,并在其方法Form\_Load中,调用自适应辅助类方法,记录窗体和其控件初始位置和大小
  • 为窗体添加SizeChanged事件,并在其方法Form\_SizeChanged中,调用自适应辅助类的自适应方法,完成自适应

完整代码

自适应窗体

public partial class Form1 : Form
{
    // 声明自适应辅助类实例  
    AutoSizeFormHelper asf = new AutoSizeFormHelper();
    public Form1()
    {
        InitializeComponent();
    }
    // 为窗体添加Load事件,并在其方法Form1_Load中,调用自适应辅助类方法,记录窗体和其控件的初始位置和大小  
    private void Form1_Load(object sender, EventArgs e)
    {
        asf.ControlInitializeSize(this);
    }
    // 为窗体添加SizeChanged事件,并在其方法Form1_SizeChanged中,调用自适应辅助类的自适应方法,完成自适应  
    private void Form1_SizeChanged(object sender, EventArgs e)
    {
        asf.ControlAutoSize(this);
    }
}

自适应辅助类

/// <summary>
/// 自适应窗体辅助类
/// </summary>
public class AutoSizeFormHelper
{
    // 窗体和其控件的初始位置和大小。  
    public class ControlRect
    {
        public int Left;
        public int Top;
        public int Width;
        public int Height;

        public ControlRect(int l, int t, int w, int h)
        {
            Left = l;
            Top = t;
            Width = w;
            Height = h;
        }
    }

    // 当前控件的位置和大小  
    public ConditionalWeakTable<Control, ControlRect> oldControls = new ConditionalWeakTable<Control, ControlRect>();

    // 当前的窗体位置和大小
    public ControlRect formRect;

    // 记录窗体和其控件的初始位置和大小
    public void ControlInitializeSize(Form mForm)
    {
        // 窗体自身位置
        this.formRect = new ControlRect(mForm.Left, mForm.Top, mForm.Width, mForm.Height);

        foreach (Control c in mForm.Controls)
        {
            ControlRect controlRect = new ControlRect(c.Left, c.Top, c.Width, c.Height);
            oldControls.Add(c, controlRect);
        }

        //记录完控件的初始位置和大小后,最大化  
        mForm.WindowState = System.Windows.Forms.FormWindowState.Maximized;
    }

    // 控件自适应大小,  
    public void ControlAutoSize(Form mForm)
    {
        // 缩放比例
        float wScale = (float)mForm.Width / (float)formRect.Width;
        float hScale = (float)mForm.Height / (float)formRect.Height;

        ControlRect data;
        foreach (Control c in mForm.Controls)
        {
            if (oldControls.TryGetValue(c, out data))
            {
                c.Left = (int)((data.Left) * wScale);//新旧控件之间的线性比例。控件位置只相对于窗体,所以只需成比例
                c.Top = (int)((data.Top) * hScale);
                c.Width = (int)(data.Width * wScale);
                c.Height = (int)(data.Height * hScale);
            }
        }
    }
}

添加新评论