Note
This is a simple example developed with VS.NET 2005 Beta 1 codename Whidbey. So, project and solution are not usable with previous versions, while code should run in previous versions without problems.
Introduction and background
Faced with and, as the matter of fact, astonished by user requirement specification for one project, where one of the requirements were that controls (some or all) on the form must be movable (runtime editable in narrower sense).
So after "brainstorming", the decision was made to make a framework to implement a UserControl
for runtime movable controls called EditableControl
. EditableControl
should be super class for any custom made control with arbitrary number and type of controls.
The idea is to allow users to adjust his/hers look and feel through positions of controls, whereby business logic behind the control stays the same (actually, user is not able to change anything except presentation).
The control should be reusable, so it inherits from UserControl
, and any other business logic control that inherits from EditableControl
will be editable too.
Original control
Control after runtime "editing"
Design
EditableControl
has four member variables for layout editing (moving): points for the origin of the moved control, destination, reference to control being moved, and an ArrayList
of controls that can be moved (for other controls).
private
Point
_point_begin
;
private
Point
_point_end
;
private
Control
_control_moving
= null
;
public
System.Collections.ArrayList
EditableControls
;
To accomplish drag&drop of the control, three mouse events must be handled by containing (hosting control, parent) as well as by every contained (child) control. Those events are: MouseDown
to detect selection of the control, MouseMove
to animate movement, and MouseUp
to detect destination point. Actually, only two events are needed: MouseDown
and MouseUp
, but animation can't hurt. Initialization hooks events to all contained child controls.
protected
virtual
void
initialize
(
)
{
foreach (Control ctrl in Controls)
{
ctrl.MouseDown += new MouseEventHandler(MouseDownEventHandler);
ctrl.MouseUp += new MouseEventHandler(MouseUpEventHandler);
ctrl.MouseMove += new MouseEventHandler(MouseMoveEventHandler);
}
return;
}
And events which are handled for each movable control and do not interfere with control's behavior (events and logic):
protected
virtual
void
MouseDownEventHandler
(
object sender
, MouseEventArgs evnt_args_mouse
)
{
int x;
int y;
if (
evnt_args_mouse.Button == MouseButtons.Left
&&
! "Core.Windows.Forms.EditableControl"
.Equals(sender.GetType().ToString())
&&
EditableControls.Contains(sender)
)
{
Point pt;
pt = Cursor.Position;
x_offset_on_client_control = evnt_args_mouse.X;
y_offset_on_client_control = evnt_args_mouse.Y;
x = x_offset_on_client_control + ((Control)sender).Location.X;
y = y_offset_on_client_control + ((Control)sender).Location.Y;
pt = new Point(x, y);
_point_begin = pt;
}
foreach (Control ctrl in Controls)
{
if (ctrl.Bounds.Contains(_point_begin))
{
_control_moving = ctrl;
}
}
return;
}
protected
virtual
void
MouseMoveEventHandler
(
object sender
, MouseEventArgs evnt_args_mouse
)
{
if (
! "Core.Windows.Forms.EditableControl"
.Equals(sender.GetType().ToString())
&&
_control_moving != null
&&
evnt_args_mouse.Button == MouseButtons.Left
)
{
Point pt = Cursor.Position;
_control_moving.Left =
(this.PointToClient(pt)).X
-
x_offset_on_client_control
;
_control_moving.Top =
(this.PointToClient(pt)).Y
-
y_offset_on_client_control
;
}
}
protected
virtual
void
MouseUpEventHandler
(
object sender
, MouseEventArgs evnt_args_mouse
)
{
if (
_control_moving != null
&&
evnt_args_mouse.Button == MouseButtons.Left
)
{
int x;
int y;
x = ((Control)sender).Location.X;
y = ((Control)sender).Location.Y;
Point pt = new Point(x, y);
_point_end = pt;
_control_moving.Location = _point_end;
_control_moving = null;
}
return;
}
Using the code
To make any control (let's say SomeUserControl
) runtime editable, inherit from EditableControl
.
public partial class SomeUserControl
: Core.Windows.Forms.EditableControl
{
public SomeUserControl()
:base()
{
InitializeComponent();
base.EditableControls.Add(this.textBox1);
base.EditableControls.Add(this.dataGridView1);
base.EditableControls.Add(this.checkBox1);
base.EditableControls.Add(this.checkedListBox1);
base.EditableControls.Add(this.button1);
base.initialize();
}
}
TODOs
- Resizable runtime controls
- Keys to control selection of moving control (Alt, Ctrl)
History
- First version by moljac++ - 2004.12.03.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.