Drawing Resizable Controls at Runtime
How to draw resizable controls at runtime

Introduction
This article will show how to draw borders around graphical objects and place them on the form, so users can manipulate the objects by dragging them around or resizing the controls. I hope this helps someone.
Background
I am involved in a project in which one tiny aspect of the application is where end users can place various objects on the forms and manipulate their properties. The application was developed in Delphi and I was curious what it would take to do something similar in .NET.
Using the Code
First, define the size of the drag handle that will appear around the control.
const int DRAG_HANDLE_SIZE = 7;
The method to actually draw the borders and the drag handles is as follows:
/// <summary>
/// Draw a border and drag handles around the control, on mouse down and up.
/// </summary>
/// <param name=""sender"" ></param >
private void DrawControlBorder(object sender)
{
Control control = (Control)sender;
//define the border to be drawn, it will be offset by DRAG_HANDLE_SIZE / 2
//around the control, so when the drag handles are drawn they will seem to be
//connected in the middle.
Rectangle Border = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE / 2,
control.Location.Y - DRAG_HANDLE_SIZE / 2),
new Size(control.Size.Width + DRAG_HANDLE_SIZE,
control.Size.Height + DRAG_HANDLE_SIZE));
//define the 8 drag handles, that has the size of DRAG_HANDLE_SIZE
Rectangle NW = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE,
control.Location.Y - DRAG_HANDLE_SIZE),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle N = new Rectangle(
new Point(control.Location.X + control.Width / 2 - DRAG_HANDLE_SIZE/2,
control.Location.Y - DRAG_HANDLE_SIZE),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle NE = new Rectangle(
new Point(control.Location.X + control.Width,
control.Location.Y - DRAG_HANDLE_SIZE),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle W = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE,
control.Location.Y + control.Height/2-DRAG_HANDLE_SIZE/2),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle E = new Rectangle(
new Point(control.Location.X + control.Width,
control.Location.Y + control.Height / 2 - DRAG_HANDLE_SIZE / 2),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle SW = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE,
control.Location.Y + control.Height),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle S = new Rectangle(
new Point(control.Location.X + control.Width / 2 - DRAG_HANDLE_SIZE/2,
control.Location.Y + control.Height),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle SE = new Rectangle(
new Point(control.Location.X + control.Width,
control.Location.Y + control.Height),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
//get the form graphic
Graphics g = this.CreateGraphics();
//draw the border and drag handles
ControlPaint.DrawBorder(g, Border, Color.Gray, ButtonBorderStyle.Dotted);
ControlPaint.DrawGrabHandle(g, NW, true, true);
ControlPaint.DrawGrabHandle(g, N, true, true);
ControlPaint.DrawGrabHandle(g, NE, true, true);
ControlPaint.DrawGrabHandle(g, W, true, true);
ControlPaint.DrawGrabHandle(g, E, true, true);
ControlPaint.DrawGrabHandle(g, SW, true, true);
ControlPaint.DrawGrabHandle(g, S, true, true);
ControlPaint.DrawGrabHandle(g, SE, true, true);
g.Dispose();
}
Next, implement the various events of the Control
object, for example, when I click on a control, I want a border and drag handles drawn around it, so in the MouseDown
event:
private void control_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Invalidate(); //unselect other control
SelectedControl = (Control)sender;
Control control = (Control)sender;
mouseX = -e.X;
mouseY = -e.Y;
control.Invalidate();
DrawControlBorder(sender);
propertyGrid1.SelectedObject = SelectedControl;
}
}
Finally, to use it, create a control at runtime and have it subscribe to the various events, for example to create a button:
Button ctrl = new Button();
ctrl.Text = "New Button";
ctrl.Location = new Point(50, 50);
ctrl.MouseEnter += new EventHandler(control_MouseEnter);
ctrl.MouseLeave += new EventHandler(control_MouseLeave);
ctrl.MouseDown += new MouseEventHandler(control_MouseDown);
ctrl.MouseMove += new MouseEventHandler(control_MouseMove);
ctrl.MouseUp += new MouseEventHandler(control_MouseUp);
Controls.Add(ctrl);
That's it. When executed, you can move the objects around, resize them in all 8 directions.
Points of Interest
If you download the source code, you'll notice that I use a timer to track the movement of the cursor. I tried to use the MouseHover
event of the form, but that executed only once when the cursor is over it or when it leaves one of the controls, and subsequently when the cursor is over one of the drag handles it will fail to recognize it. Using a timer does solve this problem, but if you have found a better way please let me know!
History
- 3/4/2008: First released