I've been trying to make my windows form application auto resizing i.e. when the user resizes the application its controls also resize accordingly and after searching online I've come across the below code in the form of a .cs file :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
public class clsResize
{
List<System.Drawing.Rectangle> _arr_control_storage = new List<System.Drawing.Rectangle>();
private bool showRowHeader = false;
public clsResize(Form _form_)
{
form = _form_; //the calling form
_formSize = _form_.ClientSize; //Save initial form size
_fontsize = _form_.Font.Size; //Font size
}
private float _fontsize { get; set; }
private System.Drawing.SizeF _formSize {get;set; }
private Form form { get; set; }
public void _get_initial_size() //get initial size//
{
var _controls = _get_all_controls(form);//call the enumerator
foreach (Control control in _controls) //Loop through the controls
{
_arr_control_storage.Add(control.Bounds); //saves control bounds/dimension
//If you have datagridview
if (control.GetType() == typeof(DataGridView))
_dgv_Column_Adjust(((DataGridView)control), showRowHeader);
}
}
public void _resize() //Set the resize
{
double _form_ratio_width = (double)form.ClientSize.Width /(double)_formSize.Width; //ratio could be greater or less than 1
double _form_ratio_height = (double)form.ClientSize.Height / (double)_formSize.Height; // this one too
var _controls = _get_all_controls(form); //reenumerate the control collection
int _pos = -1;//do not change this value unless you know what you are doing
foreach (Control control in _controls)
{
// do some math calc
_pos = 1;//increment by 1;
System.Drawing.Size _controlSize = new System.Drawing.Size((int)(_arr_control_storage[_pos].Width * _form_ratio_width),
(int)(_arr_control_storage[_pos].Height * _form_ratio_height)); //use for sizing
System.Drawing.Point _controlposition = new System.Drawing.Point((int)
(_arr_control_storage[_pos].X * _form_ratio_width),(int) (_arr_control_storage[_pos].Y * _form_ratio_height));//use for location
//set bounds
control.Bounds = new System.Drawing.Rectangle(_controlposition, _controlSize); //Put together
//Assuming you have a datagridview inside a form()
//if you want to show the row header, replace the false statement of
//showRowHeader on top/public declaration to true;
if (control.GetType() == typeof(DataGridView))
_dgv_Column_Adjust(((DataGridView)control), showRowHeader);
//Font AutoSize
control.Font = new System.Drawing.Font(form.Font.FontFamily,
(float)(((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2)
((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2)));
}
}
private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader) //if you have Datagridview
//and want to resize the column base on its dimension.
{
int intRowHeader = 0;
const int Hscrollbarwidth = 5;
if (_showRowHeader)
intRowHeader = dgv.RowHeadersWidth;
else
dgv.RowHeadersVisible = false;
for (int i = 0; i < dgv.ColumnCount; i )
{
if (dgv.Dock == DockStyle.Fill) //in case the datagridview is docked
dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
else
dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
}
}
private static IEnumerable<Control> _get_all_controls(Control c)
{
return c.Controls.Cast<Control>().SelectMany(item =>
_get_all_controls(item)).Concat(c.Controls.Cast<Control>()).Where(control =>
control.Name != string.Empty);
}
}
I added this to my project used in code as below :
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace KryptonTest
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : KryptonForm
{
clsResize _form_resize;
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
_form_resize = new clsResize(this);
this.Load = MainFormLoad;
this.Resize = MainFormResize;
}
void MainFormLoad(object sender, EventArgs e)
{
_form_resize._get_initial_size();
}
void MainFormResize(object sender, EventArgs e)
{
_form_resize._resize();
}
}
}
But when I run it I get the below error twice
How do I fix this?
CodePudding user response:
Are you sure the enum is working properly? The error message is telling you the list has less items than you're trying to call.
Index was out of range. Must be non-negativue and less than the size of the collection. Parameter name: index
CodePudding user response:
When we resize a form we normally pick some controls to get bigger and others not - it doesn't really make much sense to double the width and height of a name TextBox, or a Checkbox because you don't type/see significantly more text in them. Other items like a logging list box, email body designer TextBox etc, it makes sense to have those things resize.
Arranging a layout that resizes is quite simple: every control has an Anchor property and when the anchor for a particular side is set then the control will move or resize so there is the same distance between the control and the given edge of the container. Obviously then if a control is anchored on opposing sides, then it will stretch when the container it is in gets bigger
Some examples:
TextBox is 100 wide and 20 high, anchored on Top Left. The form is made 200 pixels wider and 200 higher. The TextBox appears not to move or grow; it remains the same distance from the top left corner
TextBox is 100 wide and 20 high, anchored on Top Right. The form is made 200 pixels wider and 200 higher. The TextBox moves 200 pixels to the Right because it is Right anchored and keeps the same distance between the form right edge. It does not grow wider; it remains the same distance from the top left corner. It does not grow taller because it is Top anchored but not Bottom anchored
TextBox is 100 wide and 20 high, anchored on Top Left Bottom Right. It is a multi line TextBox. The form is made 200 pixels wider and 200 higher. The TextBox grows 200 pixels wider and 200 pixels higher because the form has grown by 200x200 - the anchors on all sides means the textbox edges stay the same distance from the form edges
You want 3 textboxes in a row, the middle one should get wider when the form gets wider; the other two textboxes should not grow
- You anchor the left TextBox on the Top Left
- You anchor the middle TextBox on Top Left Right
- You anchor the right TextBox on the Top Right
When the form gets wider the left TextBox stays put, the right TextBox moves to the right by as much as the form got wider, the middle TextBox expands sideways by as much as the form got wider
When neither opposing side is anchored the control moves by half the distance of the resize in that direction
Don't forget you can put panels in that are anchored one way and then controls inside them that are anchored another way. For other kinds of layouts you might need a table or flow layout panel but for most UIs the anchoring system works quite well