How to make your controls moveable?

Ramy Mahrous 2 Tallied Votes 1K Views Share

Here's I wrote some code to move controls on the form
1- Assign (Control_MouseMove, Control_MouseDown, and Control_MouseUp) to the controls you need it movable.

ddanbe commented: Great! +6
//This code developed by Ramy Mahrous 
//ramyamahrous@hotmail.com
//Its contents is provided "as is", without warranty.

/// <summary>
/// Indicates whether control is pressed by mouse or not
/// </summary>
bool IsDraged = false;

/// <summary>
/// Holds the X-coordinate of the control
/// </summary>
int Control_X = 0;

/// <summary>
/// Holds the Y-coordinate of the control
/// </summary>
int Control_Y = 0;

private void Control_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
IsDraged = true;
Control_X = e.X;
Control_Y = e.Y;
}
}

private void Control_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
IsDraged = false;
}
}

private void Control_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Control active = (Control)sender;
if (IsDraged)
{
active.Left += e.X - Control_X / 12;
active.Top += e.Y - Control_Y / 12;
Control_X = e.X;
Control_Y = e.Y;
}
}
}

Dani AI

Generated

Good starting snippets from and the tighter version from — and good catch by about creating unnecessary objects. Practical advice: track the mouse offset on MouseDown, use the parent coordinate space (Parent.PointToClient(Cursor.Position)) when moving, set Capture so the control follows the cursor cleanly, and enforce parent bounds. That avoids cumulative drift and makes it easy to support panels with AutoScroll.

// attach handlers once (e.g. foreach control in a container call AttachDraggable)
private Control _dragged;
private Point _offset;

private void AttachDraggable(Control c)
{
    c.MouseDown += Control_MouseDown;
    c.MouseMove += Control_MouseMove;
    c.MouseUp += Control_MouseUp;
}

private void Control_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button != MouseButtons.Left) return;
    _dragged = (Control)sender;
    _offset = e.Location;
    _dragged.Capture = true;
}

private void Control_MouseMove(object sender, MouseEventArgs e)
{
    if (_dragged == null) return;
    var parent = _dragged.Parent;
    var p = parent.PointToClient(Cursor.Position);
    int x = Math.Max(0, Math.Min(parent.ClientSize.Width - _dragged.Width, p.X - _offset.X));
    int y = Math.Max(0, Math.Min(parent.ClientSize.Height - _dragged.Height, p.Y - _offset.Y));
    _dragged.Location = new Point(x, y);
}

private void Control_MouseUp(object sender, MouseEventArgs e)
{
    if (_dragged != null) _dragged.Capture = false;
    _dragged = null;
}

To move a PictureBox and its label together (answering ): the simplest is to encapsulate both in a UserControl so they become one draggable unit. If you must keep them separate, maintain a mapping from lead->follower and update the label after the picture moves, e.g. center the label under the picture with label.Left = pic.Left + (pic.Width - label.Width)/2; label.Top = pic.Bottom + 2;. Troubleshooting: disable Dock/Anchor while dragging, adjust for AutoScroll (add AutoScrollPosition), and watch operator precedence (e.g. e.X - (prevX/12) vs (e.X - prevX)/12) if you try scaling movement.

persianc# 0 Newbie Poster

thanks dear friend

cipher_nemo 0 Newbie Poster

Here's an even simpler example. You did unnecessary steps that can be avoided, even though yours is a good example. :)

Note: "Control" is the name of the object you want to move, so link it up in the Designer area first.

private Point pointMouse = new Point();
private Control ctrlMoved = new Control();
private bool bMoving = false;

private void Control_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
	//if not left mouse button, exit
	if (e.Button != MouseButtons.Left)
	{
		return;
	}
	// save cursor location
	pointMouse = e.Location;
	//remember that we're moving
	bMoving = true;
}

private void Control_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
	bMoving = false;
}

private void Control_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
	//if not being moved or left mouse button not used, exit
	if (!bMoving || e.Button != MouseButtons.Left)
	{
		return;
	}
	//get control reference
	ctrlMoved = (Control)sender;
	//set control's position based upon mouse's position change
	ctrlMoved.Left += e.X - pointMouse.X;
	ctrlMoved.Top += e.Y - pointMouse.Y;
}
vigor 0 Newbie Poster

Hi..
May I ask if how can I move two controls simultaneously. I have 3 instances of picturebox and 3 corresponding label at each bottom of picturebox. Picturebox are plotted on the panel inside user control. Now, I want to move specific picturebox, but what I want is that label will follow to the picturebox and place itself under picturebox. Is that possible? Please supply some codes. Thanks. :idea:

Ramy Mahrous 401 Postaholic Featured Poster

First solution came is to group them inside UserControl, and play with them like above.

vigor 0 Newbie Poster

But how can I group them? Will 'Struct' and 'Dictionary' applicable in that case? Please provide some codes.:-/:confused:

Diamonddrake 397 Master Poster

Here's an even simpler example. You did unnecessary steps that can be avoided, even though yours is a good example. :)

Note: "Control" is the name of the object you want to move, so link it up in the Designer area first.

private Point pointMouse = new Point();
private Control ctrlMoved = new Control();
private bool bMoving = false;

private void Control_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
	//if not left mouse button, exit
	if (e.Button != MouseButtons.Left)
	{
		return;
	}
	// save cursor location
	pointMouse = e.Location;
	//remember that we're moving
	bMoving = true;
}

private void Control_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
	bMoving = false;
}

private void Control_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
	//if not being moved or left mouse button not used, exit
	if (!bMoving || e.Button != MouseButtons.Left)
	{
		return;
	}
	//get control reference
	ctrlMoved = (Control)sender;
	//set control's position based upon mouse's position change
	ctrlMoved.Left += e.X - pointMouse.X;
	ctrlMoved.Top += e.Y - pointMouse.Y;
}

This is practically the same code as the OP, only you used a point instead of two ints (which is a good idea but to each their own)

I would like to point out when you declared the ctrlMoved variable, you set it to a "new control" since you are using that variable to hold reference to existing controls, That is unnecessary and you are creating an orphaned object. Same thing with the pointMouse variable. You immediately assign it to reference e.location so the "new point" is never used, its just orphaned for the garbage collector to pick up.

Either way, as always, thanks to both of you for sharing code, its always nice to see additions to the snippet library.

vigor 0 Newbie Poster

How about lines? Are they too movable and How?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.