C# Winform 界面中各控件隨着窗口大小變化


在做一項工程中,由於不確定目標平台的分辨率,而正常使用要求鋪滿整個屏幕,所以界面中的各個控件必須能夠適應窗口的變化。

首先想到的就是控件的百分比布局,但是再嘗試寫了幾個控件的Location和Size之后,發現這真是一項浩大的工程,方法是在太笨,不如將控件百分比布局作為一個類,專門來負責。

在網上找到了這種思想的代碼  

http://blog.sina.com.cn/s/blog_45eaa01a0101c7ko.html

 

經過測試是能夠完成任務的,但是仍有一定的缺陷

1.我的界面中有控件動態的隱藏和可見,在這種情況下,該代碼縮放會造成控件位置混亂

2.不能沒有改變文字的大小。

為了適應我的項目需要,對他的代碼進行了一定的修改,修改后的代碼如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SAR01
{
    class AutoSizeFormClass
    {
        //控件的初始位置信息。
        public struct controlRect
        {
            public int Left;
            public int Top;
            public int Width;
            public int Height;
        }
        //存儲控件名和他的位置
        public Dictionary<String, controlRect> oldCtrl = new Dictionary<String, controlRect>();
        int ctrlNo = 0;

        //記錄窗體和其控件的初始位置和大小,
        public void controllInitializeSize(Control mForm)
        {
            controlRect cR;
            cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height;
            
            insertDictionary(mForm.Name, cR);
            

            AddControl(mForm);//窗體內其余控件還可能嵌套控件(比如panel),要單獨抽出,因為要遞歸調用

            //this.WindowState = (System.Windows.Forms.FormWindowState)(2);//記錄完控件的初始位置和大小后,再最大化
            //0 - Normalize , 1 - Minimize,2- Maximize
        }

        private void AddControl(Control ctl)
        {
            foreach (Control c in ctl.Controls)
            {  
                
                controlRect objCtrl;
                objCtrl.Left = c.Left; objCtrl.Top = c.Top; objCtrl.Width = c.Width; objCtrl.Height = c.Height;
                insertDictionary(c.Name, objCtrl);
         
                if (c.Controls.Count > 0)
                    AddControl(c);

            }
        }

        //(3.2)控件自適應大小,
        public void controlAutoSize(Control mForm)
        {

            if (ctrlNo == 0)
            { 

           AddControl(mForm);//窗體內其余控件可能嵌套其它控件(比如panel),故單獨抽出以便遞歸調用
        }
            float wScale = (float)mForm.Width / oldCtrl[mForm.Name].Width; ;//新舊窗體之間的比例,與最早的舊窗體
            float hScale = (float)mForm.Height / oldCtrl[mForm.Name].Height; ;//.Height;

            ctrlNo = 1;//進入=1,第0個為窗體本身,窗體內的控件,從序號1開始
            
            
            AutoScaleControl(mForm, wScale, hScale);//窗體內其余控件還可能嵌套控件(比如panel),要單獨抽出,因為要遞歸調用
        }
            
            
            AutoScaleControl(mForm, wScale, hScale);//窗體內其余控件還可能嵌套控件(比如panel),要單獨抽出,因為要遞歸調用
        }

        private void AutoScaleControl(Control ctl, float wScale, float hScale)
        {
            int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0;
            //int ctrlNo = 1;//第1個是窗體自身的 Left,Top,Width,Height,所以窗體控件從ctrlNo=1開始
            foreach (Control c in ctl.Controls)
            { //**放在這里,是先縮放控件的子控件,后縮放控件本身
                //if (c.Controls.Count > 0)
                //   AutoScaleControl(c, wScale, hScale);//窗體內其余控件還可能嵌套控件(比如panel),要單獨抽出,因為要遞歸調用
                ctrLeft0 = oldCtrl[c.Name].Left;
                ctrTop0 = oldCtrl[c.Name].Top;
                ctrWidth0 = oldCtrl[c.Name].Width;
                ctrHeight0 = oldCtrl[c.Name].Height;
                //c.Left = (int)((ctrLeft0 - wLeft0) * wScale) + wLeft1;//新舊控件之間的線性比例
                //c.Top = (int)((ctrTop0 - wTop0) * h) + wTop1;
                c.Left = (int)((ctrLeft0) * wScale);//新舊控件之間的線性比例。控件位置只相對於窗體,所以不能加 + wLeft1
                c.Top = (int)((ctrTop0) * hScale);//
                c.Width = (int)(ctrWidth0 * wScale);//只與最初的大小相關,所以不能與現在的寬度相乘 (int)(c.Width * w);
                c.Height = (int)(ctrHeight0 * hScale);//
                AutoScaleFont(c);
                ctrlNo++;//累加序號
                //**放在這里,是先縮放控件本身,后縮放控件的子控件
                if (c.Controls.Count > 0)
                    AutoScaleControl(c, wScale, hScale);//窗體內其余控件還可能嵌套控件(比如panel),要單獨抽出,因為要遞歸調用

            }
        }
        private void AutoScaleFont(Control c)
        {
            string[] type = c.GetType().ToString().Split('.');
            string controlType = type[type.Length - 1];

            switch (controlType)
            {
                //case "Button":
                //    c.Font = new System.Drawing.Font("宋體", c.Height * 0.4f);
                //    break;

                case "GroupBox":
                    c.Font = new System.Drawing.Font("宋體", c.Height * 0.04f);
                    break;
            }
        }

     
 
         

private void insertDictionary(String name,controlRect cr) //添加控件名和位置,如果名稱重復則更新 { Dictionary<String, controlRect> temp = new Dictionary<String, controlRect>(); bool flag = false; foreach (var pair in oldCtrl) { if (pair.Key.ToString() == name) { temp.Add(name, cr); flag = true; } } if (flag==false) { oldCtrl.Add(name, cr); } foreach (var value in temp) { oldCtrl.Remove(value.Key.ToString()); oldCtrl.Add(value.Key,value.Value); } temp.Clear(); } } }



/////////////////////////////////////////////下面是需要自適應的窗體///////////////////////////////////////////////

using System;
using System.Windows.Forms;

 
         

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        //1.聲明自適應類實例
        AutoSizeFormClass asc = new AutoSizeFormClass();
        public Form1()
        {
            InitializeComponent();
            //如果加入"皮膚",則不能在Form1_Load中記錄控件的大小和位置,因為有些控件如dataGridView的子控件還未完成
            //而要在在Form1_SizeChanged中,第一次改變時,記錄控件的大小和位置
              this.skinEngine1.SkinFile = "EmeraldColor1.ssk";
        }
        //2. 為窗體添加Load事件,並在其方法Form1_Load中,調用類的初始化方法,記錄窗體和其控件的初始位置和大小
        private void Form1_Load(object sender, EventArgs e)
        {
           // asc.controllInitializeSize(this);
         }
        //3.為窗體添加SizeChanged事件,並在其方法Form1_SizeChanged中,調用類的自適應方法,完成自適應
        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            asc.controlAutoSize(this);
           //  this.WindowState = (System.Windows.Forms.FormWindowState)(2);//記錄完控件的初始位置和大小后,再最大化
      }

 
         


    }

 
         

}

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM