Click here to Skip to main content
12,635,149 members (22,880 online)
Click here to Skip to main content
Add your own
alternative version

Stats

65.4K views
10.9K downloads
44 bookmarked
Posted

Move and Resize Controls on a Form at Runtime (With Mouse)

, 13 Jan 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Move and resize controls on a form at runtime (with mouse)

Introduction

Sometimes, we want to move and resize controls in run time for example when we want to create some template for a form. There are some codes on the web for this but they cannot do both moving and resizing controls. Therefore, I write my own class on the basis of another CodeProject article.

Using this class, we can make resizeable and movable control with only one line of code:

ControlMoverOrResizer.Init(button1);   

Really? Yes!! :)

Background

This class uses lambda expression in event handler assignment.

internal static void Init(Control control, Control container)
{
    _moving = false;
    _resizing = false;
    _moveIsInterNal = false;
    _cursorStartPoint = Point.Empty;
    MouseIsInLeftEdge = false;
    MouseIsInLeftEdge = false;
    MouseIsInRightEdge = false;
    MouseIsInTopEdge = false;
    MouseIsInBottomEdge = false;
    WorkType = MoveOrResize.MoveAndResize;
    control.MouseDown += (sender, e) => StartMovingOrResizing(control, e);
    control.MouseUp += (sender, e) => StopDragOrResizing(control);
    control.MouseMove += (sender, e) => MoveControl(container, e);
}      

I write all fields, properties and methods static; therefore it is not needed to create an object of ControlMoverOrResizer class.

internal class ControlMoverOrResizer
{
    private static bool _moving;
    private static Point _cursorStartPoint;
    private static bool _moveIsInterNal;
    private static bool _resizing;
    private static Size _currentControlStartSize;
    internal static bool MouseIsInLeftEdge { get; set; }
    internal static bool MouseIsInRightEdge { get; set; }
    internal static bool MouseIsInTopEdge { get; set; }
    internal static bool MouseIsInBottomEdge { get; set; }

    internal enum MoveOrResize ...

    internal static MoveOrResize WorkType { get; set; } 

    internal static void Init(Control control) ...

    internal static void Init(Control control, Control container) ...

    private static void UpdateMouseEdgeProperties(Control control, Point mouseLocationInControl) ...

    private static void UpdateMouseCursor(Control control) ...

    private static void StartMovingOrResizing(Control control, MouseEventArgs e) ...

    private static void MoveControl(Control control, MouseEventArgs e) ...

    private static void StopDragOrResizing(Control control) ...
}  

Alone not private method in class is init method. When sending a control (or two with its container) to init method, it will add related methods to 3 important control events.

control.MouseDown += (sender, e) => StartMovingOrResizing(control, e);
control.MouseUp += (sender, e) => StopDragOrResizing(control);
control.MouseMove += (sender, e) => MoveControl(container, e); 

Now when user holds the mouse down on control, event calls the StartMovingOrResizing method, and this method will set movingMode or resizingMode of control:

private static void StartMovingOrResizing(Control control, MouseEventArgs e)
{
    if (_moving || _resizing)
    {
        return;
    }
    if (WorkType!=MoveOrResize.Move &&
        (MouseIsInRightEdge || MouseIsInLeftEdge || MouseIsInTopEdge || MouseIsInBottomEdge))
    {
        _resizing = true;
        _currentControlStartSize = control.Size;
    }
    else if (WorkType!=MoveOrResize.Resize)
    {
        _moving = true;
        control.Cursor = Cursors.Hand;
    }
    _cursorStartPoint = new Point(e.X, e.Y);
    control.Capture = true;
}  

When user moves the mouse cursor on control MoveControl method will call, this method calls the UpdateMouseEdgeProperties and UpdateMouseCursor functions.

UpdateMouseEdgeProperties will check which cursor is on any edge of control and will set related properties:

private static void UpdateMouseEdgeProperties(Control control, Point mouseLocationInControl)
{
	if (WorkType == MoveOrResize.Move)
	{
		return;
	}
	MouseIsInLeftEdge = Math.Abs(mouseLocationInControl.X) <= 2;
	MouseIsInRightEdge = Math.Abs(mouseLocationInControl.X - control.Width) <= 2;
	MouseIsInTopEdge = Math.Abs(mouseLocationInControl.Y ) <= 2;
	MouseIsInBottomEdge = Math.Abs(mouseLocationInControl.Y - control.Height) <= 2;
}

and UpdateMouseCursor functions will change mouse cursor if it is in the edge of control:

private static void UpdateMouseCursor(Control control)
{
	if (WorkType == MoveOrResize.Move)
	{
		return;
	}
	if (MouseIsInLeftEdge )
	{
		if (MouseIsInTopEdge)
		{
			control.Cursor = Cursors.SizeNWSE;
		}
		else if (MouseIsInBottomEdge)
		{
			control.Cursor = Cursors.SizeNESW;
		}
		else
		{
			control.Cursor = Cursors.SizeWE;
		}
	}
	else if (MouseIsInRightEdge)
	{
		if (MouseIsInTopEdge)
		{
			control.Cursor = Cursors.SizeNESW;
		}
		else if (MouseIsInBottomEdge)
		{
			control.Cursor = Cursors.SizeNWSE;
		}
		else
		{
			control.Cursor = Cursors.SizeWE;
		}
	}
	else if (MouseIsInTopEdge || MouseIsInBottomEdge)
	{
		control.Cursor = Cursors.SizeNS;
	}
	else
	{
		control.Cursor = Cursors.Default;
	}
}

Now program will callback to MoveControl function and continue in this method. It will check_resizing field (this field will set when using pressDown mouse on age of control and keep it down).

If control is in resizing mode, that edge of control where cursor is on it just moves with cursor:

if (_resizing)
{
	if (MouseIsInLeftEdge)
	{
		if (MouseIsInTopEdge)
		{
			control.Width -= (e.X - _cursorStartPoint.X);
			control.Left += (e.X - _cursorStartPoint.X); 
			control.Height -= (e.Y - _cursorStartPoint.Y);
			control.Top += (e.Y - _cursorStartPoint.Y);
		}
		else if (MouseIsInBottomEdge)
		{
			control.Width -= (e.X - _cursorStartPoint.X);
			control.Left += (e.X - _cursorStartPoint.X);
			control.Height = (e.Y - _cursorStartPoint.Y)                   
		             + _currentControlStartSize.Height; 
		}
		else
		{
			control.Width -= (e.X - _cursorStartPoint.X);
			control.Left += (e.X - _cursorStartPoint.X) ;
		}
	}
	else if (MouseIsInRightEdge)
	{
		if (MouseIsInTopEdge)
		{
			control.Width = (e.X - _cursorStartPoint.X) 
                            + _currentControlStartSize.Width;
			control.Height -= (e.Y - _cursorStartPoint.Y);
			control.Top += (e.Y - _cursorStartPoint.Y); 
 
		}
		else if (MouseIsInBottomEdge)
		{
			control.Width = (e.X - _cursorStartPoint.X) 
                            + _currentControlStartSize.Width;
			control.Height = (e.Y - _cursorStartPoint.Y) 
                            + _currentControlStartSize.Height;                    
		}
		else
		{
			control.Width = (e.X - _cursorStartPoint.X) 
                           +_currentControlStartSize.Width;
		}
	}
	else if (MouseIsInTopEdge)
	{
		control.Height -= (e.Y - _cursorStartPoint.Y);
		control.Top += (e.Y - _cursorStartPoint.Y);
	}
	else if (MouseIsInBottomEdge)
	{
		control.Height = (e.Y - _cursorStartPoint.Y) 
                   + _currentControlStartSize.Height;                    
	}
	else
	{
		 StopDragOrResizing(control);
	}
}     

Else if control is in moving mode (control goes to moving mode when user presses mouse down inside of control and keeps it down), the position of control will move with cursor:

else if (_moving)
{
	_moveIsInterNal = !_moveIsInterNal;
	if (!_moveIsInterNal)
	{
		int x = (e.X - _cursorStartPoint.X) + control.Left;
		int y = (e.Y - _cursorStartPoint.Y) + control.Top;
		control.Location = new Point(x, y);
	}
}

At last, when user releases the mouse, StopDragOrResizing method will be called and it will reset moving mode and resizing mode to false and update the cursor.

private static void StopDragOrResizing(Control control)
{
	_resizing = false;
	_moving = false;
	control.Capture = false;
	UpdateMouseCursor(control);
} 

Using the Code

For enable resizing and moving mode for a control, we just call init method inMoveAndResizeControls class in send control to it.

MoveAndResizeControls.Init(button1); 

If we want to change container of control (for example, when control is filled in its container), we just send container as the second parameter.

ControlMoverOrResizer.Init(button2,panel1); 

In some cases, we just want one of resizing or moving for controls in this case we just set the WorkType property in the ControlMoverOrResizer class with one of these values:

internal enum MoveOrResize
{
	Move,
	Resize,
	MoveAndResize
}

In the demo example that is uploaded here, controls can be moved and resized by mouse. Also, a combobox is in demo form who will help you select worktype ("move", "resize" or "move and resize").

using System;
using System.Windows.Forms;
using ControlManager;
namespace MoveAndResizeControls
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ControlMoverOrResizer.Init(button1);
            ControlMoverOrResizer.Init(groupBox1);
            ControlMoverOrResizer.Init(textBox1);
            ControlMoverOrResizer.Init(button2,panel1);
            comboBox1.SelectedIndex = 0;
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (comboBox1.SelectedIndex)
            {
                case 0:
                    ControlMoverOrResizer.WorkType=ControlMoverOrResizer.MoveOrResize.MoveAndResize;
                    break;
                case 1:
                    ControlMoverOrResizer.WorkType = ControlMoverOrResizer.MoveOrResize.Move;
                    break;
                case 2:
                    ControlMoverOrResizer.WorkType = ControlMoverOrResizer.MoveOrResize.Resize;
                    break;
            }
        }
    }
}    

Points of Interest

If you want to save and load changes, you can use these methods:

  • GetSizeAndPositionOfControlsToString
  • SetSizeAndPositionOfControlsFromString

This is form after move and resize controls:

My sincere thanks for your time and consideration.
Best wishes.

History

  • 2014/01/10: As of publication, version 1.0.0.0
  • 2014/02/09: As of update, version 1.1.0.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

seyyed hamed monem
Software Developer
Iran (Islamic Republic of) Iran (Islamic Republic of)
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionGetSizeAndPositionOfControlsToString and SetSizeAndPositionOfControlsFromString is Not Working Pin
Member 1201273113-Jul-16 22:45
memberMember 1201273113-Jul-16 22:45 
Questionthanks Pin
Member 1087438827-Jun-16 19:11
memberMember 1087438827-Jun-16 19:11 
QuestionExactly what I wanted! Pin
Member 1242039928-Mar-16 0:16
memberMember 1242039928-Mar-16 0:16 
GeneralMy vote of 5 Pin
Bruno Alvarez2-Mar-16 16:34
memberBruno Alvarez2-Mar-16 16:34 
QuestionBest Commercial Solution Pin
arocca6524-Feb-16 21:47
memberarocca6524-Feb-16 21:47 
PraiseThanks a lot!! Pin
Member 122393319-Jan-16 23:48
memberMember 122393319-Jan-16 23:48 
QuestionThanks Pin
swatipujari2519-Aug-15 1:02
memberswatipujari2519-Aug-15 1:02 
GeneralMy vote of 5 Pin
Member 778471518-May-15 8:47
memberMember 778471518-May-15 8:47 
QuestionRe-size panel control Pin
SachinSutar7-Apr-15 16:33
memberSachinSutar7-Apr-15 16:33 
AnswerRe: Re-size panel control Pin
Member 123627012-Mar-16 12:11
memberMember 123627012-Mar-16 12:11 
QuestionUsing this class with a user control Pin
AleMoon696930-Oct-14 8:32
memberAleMoon696930-Oct-14 8:32 
QuestionThat there is a bug when I try to change the size of ListBox or ComboBox Pin
Member 35223456-Oct-14 20:53
memberMember 35223456-Oct-14 20:53 
GeneralThanks Pin
Member 1099147130-Sep-14 5:47
memberMember 1099147130-Sep-14 5:47 
GeneralRe: Thanks Pin
zomorrod.company30-Sep-14 8:52
professionalzomorrod.company30-Sep-14 8:52 
QuestionCan you write the code for Vb? Pin
Member 1049181330-Jul-14 15:12
memberMember 1049181330-Jul-14 15:12 
AnswerRe: Can you write the code for Vb? Pin
zomorrod.company5-Aug-14 6:57
professionalzomorrod.company5-Aug-14 6:57 
GeneralRe: Can you write the code for Vb? Pin
doquigley16-Sep-14 15:33
memberdoquigley16-Sep-14 15:33 
AnswerRe: Can you write the code for Vb? Pin
zomorrod.company17-Sep-14 8:42
professionalzomorrod.company17-Sep-14 8:42 
AnswerRe: Can you write the code for Vb? Pin
EzequielKees2-Jun-16 22:08
memberEzequielKees2-Jun-16 22:08 
QuestionThanks Pin
Skynet197011-Jul-14 4:46
memberSkynet197011-Jul-14 4:46 
AnswerRe: Thanks Pin
zomorrod.company11-Jul-14 13:06
professionalzomorrod.company11-Jul-14 13:06 
GeneralRe: Thanks Pin
Skynet197016-Jul-14 23:55
memberSkynet197016-Jul-14 23:55 
QuestionGreat...Thank you! Pin
Member 1052168122-May-14 15:06
memberMember 1052168122-May-14 15:06 
QuestionCapturing When a Move or Resize is Over Pin
Chris Hartnell24-Apr-14 6:12
memberChris Hartnell24-Apr-14 6:12 
Questionhow to remove this feature from control Pin
MBSMBS9-Feb-14 10:47
memberMBSMBS9-Feb-14 10:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161208.2 | Last Updated 13 Jan 2014
Article Copyright 2014 by seyyed hamed monem
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid