Advertisement:

Skystone Software

http://www.SkystoneSoftware.com

Scott Waletzko's Blog
Draggable Rectangle Control
Published: 10/22/2008
XMl / RSS

Here's the beginnings of a user control that allows you to draw a rectangle on a form (add the control using Control.Add) that the user can then resize and move around the form as they see fit. There's plenty you can do to enhance the code - I wrote the control as a prototype to get someone started on making their own draggable / resizable rectangles.

VB:

    ' TODO: add a property for each of these settings... 
    Private m_ptMinSize As Point = New Point(25, 25) 
    Private m_boolAllowDrag As Boolean = True 
    Private m_boolAllowResize As Boolean = True 
    Private m_clrBorderColor As Color = Color.Black 

    ' internal variables... 
    Private m_boolFocused As Boolean = False 
    Private m_boolDragging As Boolean = False 
    Private m_boolSizing As Boolean = False 
    Private m_crSizeType As Cursor = Cursors.Default 
    Private m_ptDragOffset As Point = New Point(0, 0) 

    Private Sub DraggableRectangle_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown 
        If (m_boolAllowDrag) Then m_boolDragging = (Cursor = Cursors.Hand) 
        If m_boolAllowResize Then m_boolSizing = Not m_boolDragging 
        m_ptDragOffset = New Point(e.X, e.Y) 
    End Sub 

    Private Sub DraggableRectangle_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove 
        ' perform drag... 
        If m_boolDragging Then 
            Me.Top = Me.Top + (e.Y - m_ptDragOffset.Y) 
            Me.Left = Me.Left + (e.X - m_ptDragOffset.X) 
            Exit Sub 
        End If 
        ' perform size... 
        If m_boolSizing Then 
            Select Case Cursor 
                Case Cursors.SizeNS 
                    If e.Y >= m_ptMinSize.Y Then Me.Height = e.Y 
                Case Cursors.SizeWE 
                    If e.X >= m_ptMinSize.X Then Me.Width = e.X 
                Case Else 
                    If e.Y >= m_ptMinSize.Y Then Me.Height = e.Y 
                    If e.X >= m_ptMinSize.X Then Me.Width = e.X 
            End Select 
            'redraw... 
            Me.Invalidate() 
            Exit Sub 
        End If 
        ' alter cursor if not dragging or sizing... 
        If (e.X = Me.Width - 2 Or e.X = Me.Width - 3) And _ 
            (e.Y = Me.Height - 2 Or e.Y = Me.Height - 3) Then 
            ' bottom right corner... 
            Me.Cursor = Cursors.SizeNWSE 
        ElseIf (e.X = Me.Width - 2 Or e.X = Me.Width - 3) Then 
            ' right side... 
            Me.Cursor = Cursors.SizeWE 
        ElseIf (e.Y = Me.Height - 2 Or e.Y = Me.Height - 3) Then 
            ' bottom side... 
            Me.Cursor = Cursors.SizeNS 
        Else 
            Me.Cursor = Cursors.Hand 
        End If 
    End Sub 

    Private Sub DraggableRectangle_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp 
        m_boolDragging = False 
        m_boolSizing = False 
    End Sub 

    Private Sub DraggableRectangle_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter 
        m_boolFocused = True 
        Me.Invalidate() 
    End Sub 

    Private Sub DraggableRectangle_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave 
        m_boolFocused = False 
        Me.Invalidate() 
    End Sub 

    Private Sub DraggableRectangle_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint 

        ' draw borders... 

        ' TODO: set pen color according to a property on the control... 
        Dim clsPen As Pen = New Pen(m_clrBorderColor, 1) 

        ' set up pen appearance... 
        If m_boolFocused Then 
            clsPen.DashStyle = Drawing2D.DashStyle.Dash 
        Else 
            clsPen.DashStyle = Drawing2D.DashStyle.Solid 
        End If 

        ' draw border... 
        e.Graphics.DrawRectangle(clsPen, New Rectangle(New Point(1, 1), New Size(Me.Size.Width - 2, Me.Size.Height - 2))) 

    End Sub 
C#:
	// TODO: add a property for each of these settings... 
	private Point m_ptMinSize = new Point(25, 25);
	private bool m_boolAllowDrag = true;
	private bool m_boolAllowResize = true;
	private Color m_clrBorderColor = Color.Black;

	// internal variables... 
	private bool m_boolFocused = false;
	private bool m_boolDragging = false;
	private bool m_boolSizing = false;
	private Cursor m_crSizeType = Cursors.Default;
	private Point m_ptDragOffset = new Point(0, 0);

	private void DraggableRectangle_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
	{
		if (m_boolAllowDrag)
			m_boolDragging = (Cursor == Cursors.Hand);
		if (m_boolAllowResize)
			m_boolSizing = ! m_boolDragging;
		m_ptDragOffset = new Point(e.X, e.Y);
	}

	private void DraggableRectangle_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
	{
		// perform drag... 
		if (m_boolDragging)
		{
			this.Top = this.Top + (e.Y - m_ptDragOffset.Y);
			this.Left = this.Left + (e.X - m_ptDragOffset.X);
			return;
		}
		// perform size... 
		if (m_boolSizing)
		{
			if (Cursor == Cursors.SizeNS)
			{
					if (e.Y >= m_ptMinSize.Y)
						this.Height = e.Y;
			}
			else if (Cursor == Cursors.SizeWE)
			{
					if (e.X >= m_ptMinSize.X)
						this.Width = e.X;
			}
			else
			{
					if (e.Y >= m_ptMinSize.Y)
						this.Height = e.Y;
					if (e.X >= m_ptMinSize.X)
						this.Width = e.X;
			}
			//redraw... 
			this.Invalidate();
			return;
		}
		// alter cursor if not dragging or sizing... 
		if ((e.X == this.Width - 2 | e.X == this.Width - 3) & (e.Y == this.Height - 2 | e.Y == this.Height - 3))
		{
			// bottom right corner... 
			this.Cursor = Cursors.SizeNWSE;
		}
		else if (e.X == this.Width - 2 | e.X == this.Width - 3)
		{
			// right side... 
			this.Cursor = Cursors.SizeWE;
		}
		else if (e.Y == this.Height - 2 | e.Y == this.Height - 3)
		{
			// bottom side... 
			this.Cursor = Cursors.SizeNS;
		}
		else
			this.Cursor = Cursors.Hand;
	}

	private void DraggableRectangle_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
	{
		m_boolDragging = false;
		m_boolSizing = false;
	}

	private void DraggableRectangle_MouseEnter(object sender, System.EventArgs e)
	{
		m_boolFocused = true;
		this.Invalidate();
	}

	private void DraggableRectangle_MouseLeave(object sender, System.EventArgs e)
	{
		m_boolFocused = false;
		this.Invalidate();
	}

	private void DraggableRectangle_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
	{

		// draw borders... 

		// TODO: set pen color according to a property on the control... 
		Pen clsPen = new Pen(m_clrBorderColor, 1F);

		// set up pen appearance... 
		if (m_boolFocused)
			clsPen.DashStyle = Drawing2D.DashStyle.Dash;
		else
			clsPen.DashStyle = Drawing2D.DashStyle.Solid;

		// draw border... 
		e.Graphics.DrawRectangle(clsPen, new Rectangle(new Point(1, 1), new Size(this.Size.Width - 2, this.Size.Height - 2)));

	}

If you use the C# version of the above code, don't forget to add the event handler hook code to the Initialize event of the control.



Questions or Comments? .

VB to C# and C# to VB translation provided by Instant C# and Instant VB.