In order to improve the user's experience, the form can no longer be fixed in size (the user can't change the size of the form at will), so to make the form adapt to the resolution of the computer screen, the controls in the form should change with the change proportion of the form.
Through online search and learning, it is found that there are several good methods for bigwigs, so their code is added to their own projects for testing. Although they can realize the function of proportion change, they sometimes have problems such as control dislocation (method 1 below), slow page loading, etc. Without finding a better way, first sum up these two methods.
1, Class AutoSizeFormClass
Refer to the original link of big brother: Improving the adaption of C ා WinForm form and its controls,Controls in c-winform interface change with window size
1. Function of class:
(1) use it to record the initial position and size of the form and its controls;
(2) according to the changed size of the window, the horizontal and vertical direction of the control can be changed proportionally, that is, adaptive;
2. AutoSizeFormClass code
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; namespace FB100_RS485 { class AutoSizeFormClass { //(1) . declares a structure that records only the initial position and size of the form and its controls. public struct controlRect { public int Left; public int Top; public int Width; public int Height; } //(2) . declare 1 object //Note that you cannot use the list of controls to record List nCtrl; because of the association of controls, the current size is always recorded. // public List oldCtrl= new List(); / / the greater than and less than signs in western languages are filtered out here. They can only be changed to Chinese ones. You need to change back to western languages in use //public List<controlRect> oldCtrl = new List<controlRect>();//20200305 //Stores the control name and its location public Dictionary<String, controlRect> oldCtrl = new Dictionary<String, controlRect>();//20200305 int ctrlNo = 0;//1; //(3) . create two functions //(3.1) record the initial position and size of the form and its controls, public void controllInitializeSize(Control mForm) { controlRect cR; cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height; //oldCtrl.Add(cR); / / the first one is "form itself", which can only be added once / / 20200305 oldCtrl.Add(mForm.Name, cR);//20200305 insertDictionary(mForm.Name, cR);//20200305 AddControl(mForm);//The rest of the controls in the form may also be nested (such as panel), which should be extracted separately because of recursive call //this.WindowState = (System.Windows.Forms.FormWindowState)(2); / / after recording the initial position and size of the control, maximize //0 - Normalize , 1 - Minimize,2- Maximize } private void AddControl(Control ctl) { foreach (Control c in ctl.Controls) { //**In this case, the sub control of the control is recorded first, and then the control itself is recorded //if (c.Controls.Count > 0) // AddControl(c); / / other controls in the form may also be nested (such as panel), which should be extracted separately because they need to be called recursively controlRect objCtrl; objCtrl.Left = c.Left; objCtrl.Top = c.Top; objCtrl.Width = c.Width; objCtrl.Height = c.Height; //oldCtrl.Add(c.Name, objCtrl);//20200305 if (oldCtrl.ContainsKey(c.Name))//If the key already exists, change the corresponding value { //MessageBox.Show("successfully changed value"); oldCtrl[c.Name] = objCtrl; } else//If the key does not exist, add { oldCtrl.Add(c.Name, objCtrl);//The first one is "form itself". You can only add it once / / 20200305 } insertDictionary(c.Name, objCtrl); //**Put here, first record the control itself, then record the child controls of the control if (c.Controls.Count > 0) AddControl(c);//The rest of the controls in the form may also be nested (such as panel), which should be extracted separately because of recursive call } } //(3.2) control adaptive size, public void controlAutoSize(Control mForm) { if (ctrlNo == 0) { //*If you record the original size and position of the control in form1 \ u load of the form, there is no problem normally, but there will be a problem if you want to add skin, because some controls, such as dataGridView's child controls, have not been completed, and the number is small //*To record the original size and position of the control when changing the size for the first time in form1 ﹣ sizechanged of the form, the child controls of all controls have been formed here controlRect cR; // cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height; cR.Left = 0; cR.Top = 0; cR.Width = mForm.PreferredSize.Width; cR.Height = mForm.PreferredSize.Height; //oldCtrl.Add(mForm.Name, cR); / / the first one is "form itself". You can only add it once / / 20200305 if (oldCtrl.ContainsKey(mForm.Name))//If the key already exists, change the corresponding value { //MessageBox.Show("successfully changed value"); oldCtrl[mForm.Name] = cR; } else//If the key does not exist, add { oldCtrl.Add(mForm.Name, cR);//The first one is "form itself". You can only add it once / / 20200305 } AddControl(mForm);//Other controls in the form may be nested with other controls (such as panel), so they can be extracted separately to call recursively } //float wScale = (float)mForm.Width / (float)oldCtrl[0].Width; / / the ratio between the old and new forms, and the oldest form //float hScale = (float)mForm.Height / (float)oldCtrl[0].Height;//.Height; float wScale = (float)mForm.Width / oldCtrl[mForm.Name].Width; ;//The ratio between the old and new forms to the oldest float hScale = (float)mForm.Height / oldCtrl[mForm.Name].Height; ;//.Height; ctrlNo = 1;//Enter = 1, the 0 is the form itself, the control in the form, starting from the No. 1 AutoScaleControl(mForm, wScale, hScale);//The rest of the controls in the form may also be nested (such as panel), which should be extracted separately because of recursive call } private void AutoScaleControl(Control ctl, float wScale, float hScale) { int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0; //Int Ctrl no = 1; / / the first is the Left,Top,Width,Height of the form itself, so the form control starts from Ctrl no = 1 foreach (Control c in ctl.Controls) { //**In this case, the child control of the control is scaled first, and then the control itself is scaled //if (c.Controls.Count > 0) // Autoscale control (C, wscale, hscale); / / other controls in the form may also nest controls (such as panel), which need to be extracted separately because they need to be called recursively /* ctrLeft0 = oldCtrl[ctrlNo].Left; ctrTop0 = oldCtrl[ctrlNo].Top; ctrWidth0 = oldCtrl[ctrlNo].Width; ctrHeight0 = oldCtrl[ctrlNo].Height; */ 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; / / linear ratio between new and old controls //c.Top = (int)((ctrTop0 - wTop0) * h) + wTop1; c.Left = (int)((ctrLeft0) * wScale);//Linear scale between old and new controls. Control position is only relative to the form, so + wLeft1 cannot be added c.Top = (int)((ctrTop0) * hScale);// c.Width = (int)(ctrWidth0 * wScale);//It is only related to the original size, so it cannot be multiplied by the current width (int)(c.Width * w); c.Height = (int)(ctrHeight0 * hScale);// AutoScaleFont(c); ctrlNo++;//Accumulating ordinal number //**In this case, first scale the control itself, and then scale the sub control of the control if (c.Controls.Count > 0) AutoScaleControl(c, wScale, hScale);//The rest of the controls in the form may also be nested (such as panel), which should be extracted separately because of recursive call if (ctl is DataGridView) { DataGridView dgv = ctl as DataGridView; Cursor.Current = Cursors.WaitCursor; int widths = 0; for (int i = 0; i < dgv.Columns.Count; i++) { dgv.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.AllCells); // Auto adjust column width widths += dgv.Columns[i].Width; // Calculate the width and } if (widths >= ctl.Size.Width) // If the width of the adjustment column is greater than the set column width dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells; // Adjust the mode of the column automatically else dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; // Fill if less than Cursor.Current = Cursors.Default; } } } 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("Tahoma", c.Height * 0.4f); // break; //case "GroupBox": // c.Font = new System.Drawing.Font("Tahoma", c.Height * 0.06f); // break; } } private void insertDictionary(String name, controlRect cr) //Add control name and location, update if name is duplicate { 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(); } } }
3. Usage
1) copy the adaptive class into your project namespace as a whole, and then do three steps in the window that needs to be adaptive;
2) declare adaptive class instances;
3) add the Load event to the form, and call the initialization method of the class in its method form1 Load to record the initial position and size of the form and its controls;
4) add SizeChanged event to the form, and in its method form1 ﹣ SizeChanged, call the class's adaptive method to complete the adaptation;
Add the code in the form code as follows:
namespace FB100_RS485 { public partial class mainForm : Form { //1. Declare an adaptive class instance AutoSizeFormClass asc = new AutoSizeFormClass(); public mainForm() { InitializeComponent(); //Eliminate flicker during data update dataGridView2.DoubleBufferedDataGirdView(true); //If skin is added, the size and location of the control cannot be recorded in form1 \ load, because some controls, such as the child controls of dataGridView, have not been completed //In form1 ﹣ sizechanged, record the size and position of the control the first time skinEngine1.SkinFile = System.Environment.CurrentDirectory + @"\DiamondBlue.ssk"; //Select skin file } /// <summary> ///Form loading, initializing /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void mainForm_Load(object sender, EventArgs e) { //2. Add the Load event to the form, and call the initialization method of the class in its method form1 Load to record the initial position and size of the form and its controls //asc.controllInitializeSize(this); //RS485 communication configuration default parameters rs232_init(); //Public control initialization comm_control_init(); } private void mainForm_SizeChanged(object sender, EventArgs e) { //3. Add the SizeChanged event to the form, and call the class's adaptive method in its method form1 ﹣ SizeChanged to complete the adaptation asc.controlAutoSize(this); } } }
4. Summary
(1) page loading is slow, which may cause control dislocation in some cases;
(2) when the interface becomes larger, the text in the control will not follow the change, the spacing between the controls will become large, and the overall view is not very harmonious;
2, Method 2
1. Reference to the original link: Scale the size of C ා WinForm control in proportion to the size of the form
2. Code
public mainForm() { InitializeComponent(); x = this.Width; y = this.Height; setTag(this); } #region control size scales equally with form size private float x;//Defines the width of the current form private float y;//Defines the height of the current form private void setTag(Control cons) { foreach (Control con in cons.Controls) { con.Tag = con.Width + ";" + con.Height + ";" + con.Left + ";" + con.Top + ";" + con.Font.Size; if (con.Controls.Count > 0) { setTag(con); } } } private void setControls(float newx, float newy, Control cons) { //Traverse the control in the form and reset the value of the control foreach (Control con in cons.Controls) { //Gets the Tag property value of the control and stores the string array after splitting if (con.Tag != null) { string[] mytag = con.Tag.ToString().Split(new char[] { ';' }); //Determines the value of the control based on the scale of the form scale con.Width = Convert.ToInt32(System.Convert.ToSingle(mytag[0]) * newx);//width con.Height = Convert.ToInt32(System.Convert.ToSingle(mytag[1]) * newy);//height con.Left = Convert.ToInt32(System.Convert.ToSingle(mytag[2]) * newx);//left con.Top = Convert.ToInt32(System.Convert.ToSingle(mytag[3]) * newy);//top Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;//font size con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit); if (con.Controls.Count > 0) { setControls(newx, newy, con); } } } } private void mainForm_Resize(object sender, EventArgs e) { //Be sure to set the MinimumSize property of the form and the variable minimum size in the property settings //When the form is reduced to a certain extent, the controls in the form will produce a certain degree of dislocation! float newx = (this.Width) / x; float newy = (this.Height) / y; setControls(newx, newy, this); } #endregion
3. Attention
(1) do not forget the width and height settings in initialization;
(2) the form1 ﹣ Resize method needs to manually set the Resize method in the "properties" of the form (find the Resize method in the figure below, and double-click the blank space behind it);
(3) if you do not need to scale the font, you can comment out the following two lines of code.
Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;//font size con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
Conclusion:
The form cannot be shrunk infinitely, because when the form is shrunk to a certain extent, the controls in the form will be misplaced, so it is necessary to set the minimum size of the form (by setting the MinimumSize property of the form).