Introduction
This is my second post which tackles auto form resizing. My previous tip can be found here. I am fascinated with how the controls resize themselves to their containers at runtime. Though it is easy to imagine, sometimes the question which some programmer would ask is "Where do I start?".
Background
In the program, I use the IEnumerable
Interface and place it inside a class so it can be accessible to every form. You just reference the exact class name. Feel free to comment.
Using the Code
This is the default namespace of C#. Since this is C#, you should add this to import
statement using System.Collections;
in a class so you can use the array collection. Just create a new form. Copy this code below. The class is included in the attached file.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
The collections are a good way to keep track of objects that your application might need to dynamically create and destroy at runtime. You can store or add an item of any data type. A friendly reminder, don't forget to include the System.Collections.Generic
namespace in case you miss it to safeguard against inappropriate data types being added in the collection. You can create your own variable name if you want as long as it is understandable. Inside your MainForm
, i.e. Form1
:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
clsResize _form_resize;
public Form1()
{
InitializeComponent();
_form_resize = new clsResize(this);
this.Load += new EventHandler(_Load); this.Resize += new EventHandler(_Resize); }
Below is the form load event. At this point, initial values are stored in the collection for later calculations. This will store all values into ArrayList
inside the class.
private void _Load(object sender, EventArgs e)
{
_form_resize._get_initial_size();
}
Below is the resize
event, This will call the _resize
event inside the class for later calculations.
private void _Resize(object sender, EventArgs e)
{
_form_resize._resize();
}
}
}
Inside the class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
This is private
declaration inside the class, no other static
definition has been included for safety purposes.
List<System.Drawing.Rectangle> _arr_control_storage = new List<System.Drawing.Rectangle>();
private bool showRowHeader = false;
public clsResize(Form _form_)
{
form = _form_; _formSize = _form_.ClientSize; _fontsize = _form_.Font.Size; }
private float _fontsize { get; set; }
private System.Drawing.SizeF _formSize {get;set; }
private Form form { get; set; }
This event gets / records the initial size and location of the controls inside the form:
public void _get_initial_size() {
var _controls = _get_all_controls(form); foreach (Control control in _controls) {
_arr_control_storage.Add(control.Bounds); if (control.GetType() == typeof(DataGridView))
_dgv_Column_Adjust(((DataGridView)control), showRowHeader);
}
}
This event sets the control size based on the ratio of adjustment. As you can see, I removed the condition with this kind of statement: (if current_form size < initial_form size
), then return to initial size. Using the code below, the control resizes itself to its container if the current form size is less than the initial form size.
public void _resize() {
double _form_ratio_width = (double)form.ClientSize.Width /(double)_formSize.Width; double _form_ratio_height = (double)form.ClientSize.Height / (double)_formSize.Height; var _controls = _get_all_controls(form); int _pos = -1; foreach (Control control in _controls)
{
_pos += 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));
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));
control.Bounds = new System.Drawing.Rectangle(_controlposition, _controlSize);
if (control.GetType() == typeof(DataGridView))
_dgv_Column_Adjust(((DataGridView)control), showRowHeader);
control.Font = new System.Drawing.Font(form.Font.FontFamily,
(float)(((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2) +
((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2)));
}
}
I included this one if you have a datagridview
and you want to resize the column base on its container.
private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader) {
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) dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
else
dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
}
}
In the attached project, I have added a sample program with complete code for reference purposes.
Points of Interest
The code is easy to understand. Enjoy!
History
- March 27, 2014 - First post
- April 06, 2014 - Revised code (Resized the control even if the current form size is less than the initial)