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);
            }
            
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章