1. I created a form object called ResizeableForm, which inherits from System.Windows.Forms.
2. I created an AbstractControl object, which Has-A System.Windows.Forms.Control on it
3. I created an AbstractControlCollection object, which inherits from List<AbstractControl>. This simply provides a quicker means to do bulk operations on my collection of AbstractControls.
When the ResizeableForm gets painted, I initialize my AbstractControlCollection (if it is null):
private void onFormPaint(object sender, PaintEventArgs e)
{
if (_controls == null)
_controls = new AbstractControlCollection(this);
}
I also added a Resize event handler to make a call to my AbstractControlCollection.Resize() method:
private void onFormResize(object sender, EventArgs e)
{
if (_controls == null)
return;
_controls.Resize();
}
Obviously, the above code requires that you link up these delegates to the form's event handlers with the following lines:
this.Paint += new PaintEventHandler(onFormPaint);
this.Resize += new EventHandler(onFormResize);
The abstractcontrol object keeps track of ratios that the original control had, in terms of width and height, as well as distance from the top and left of the form. Below is the class:
/// <summary>
/// Stores information about a form, and provides a quick means
/// to resize a control when a form is resized
/// </summary>
public class AbstractControl
{
/// <summary>
/// The real control associated with this control
/// </summary>
Control _associatedControl;
/// <summary>
/// The form associated with the control
/// </summary>
ResizableForm _parentForm;
/// <summary>
/// Original Height ratio
/// </summary>
double _originalHeightRatio;
/// <summary>
/// Original width ratio
/// </summary>
double _originalWidthRatio;
/// <summary>
/// Original X Location of the control
/// </summary>
double _originalXRatio;
/// <summary>
/// Original Y Location of the form
/// </summary>
double _originalYRatio;
/// <summary>
/// The handle associated with the associated control
/// </summary>
IntPtr _handle;
public AbstractControl(Control c, ResizableForm originalForm)
{
_parentForm = originalForm;
_associatedControl = c;
_handle = c.Handle;
_originalHeightRatio = (double)c.Height / (double)originalForm.Height;
_originalWidthRatio = (double)c.Width / (double)originalForm.Width;
_originalXRatio = (double)c.Location.X / (double)originalForm.Width;
_originalYRatio = (double)c.Location.Y / (double)originalForm.Height;
}
/// <summary>
/// Public access to this control's handle
/// </summary>
public IntPtr Handle
{
get { return _handle; }
}
/// <summary>
/// Provides a means to resize the control based on the new form size
/// </summary>
public void Resize()
{
int newWidth = (int)((double)(_parentForm.Width * _originalWidthRatio));
int newHeight = (int)((double)(_parentForm.Height * _originalHeightRatio));
int newX = (int)((double)(_parentForm.Width * _originalXRatio));
int newY = (int)((double)(_parentForm.Height * _originalYRatio));
_associatedControl.Width = newWidth;
_associatedControl.Height = newHeight;
_associatedControl.Location = new System.Drawing.Point(newX, newY);
}
So, the remaining piece of the code is the Abstract Control Collection:
/// <summary>
/// Represents a collection of abstract controls
/// </summary>
public class AbstractControlCollection : List<AbstractControl>
{
/// <summary>
/// Form associated with the control collection
/// </summary>
ResizableForm _originalForm;
/// <summary>
/// Default constructor - adds controls to the collection based on the controls on the form
/// </summary>
/// <param name="originalForm">Form associated with the collection</param>
public AbstractControlCollection(ResizableForm originalForm)
{
_originalForm = originalForm;
addControls(originalForm);
}
/// <summary>
/// Method to add all controls and children controls to the collection
/// </summary>
/// <param name="baseControl">Control to add child controls from</param>
private void addControls(Control baseControl)
{
foreach (Control c in baseControl.Controls)
{
AbstractControl abstractControl = new AbstractControl(c, _originalForm);
if (!this.Contains(abstractControl, true))
this.Add(abstractControl);
addControls(c);
}
}
/// <summary>
/// Quick way to resize all the controls on the form at the same time
/// </summary>
public void Resize()
{
foreach (AbstractControl c in this)
c.Resize();
}
/// <summary>
/// Separate contains function to check to see if the collection contains a control
/// </summary>
/// <param name="control">Control to search for</param>
/// <param name="overrideIndicator">Overload var</param>
/// <returns>True if the collection contains the searched control</returns>
public bool Contains(AbstractControl control, bool overrideIndicator)
{
foreach (AbstractControl c in this)
{
if (control.Handle == c.Handle)
return true;
}
return false;
}
}
Conclusion
To use this code, simply add the files to your solution, and when creating a form, simply have it inhert from ResizeableForm, instead of System.Windows.Forms.Form. Everything else takes care of itself
No comments:
Post a Comment