Click here to Skip to main content
15,881,709 members
Articles / Desktop Programming / Windows Forms

Owner Drawn Resizable Control

Rate me:
Please Sign up or sign in to vote.
4.70/5 (16 votes)
30 Jan 2007CPOL14 min read 105.6K   2.7K   40  
Creating a custom control that you can resize at runtime from all four corners.
Public Class SizerControl

    'Hotspot rectangles
    Private mNWRect As Rectangle
    Private mNERect As Rectangle
    Private mSWRect As Rectangle
    Private mSERect As Rectangle

    'Hotspot mousedown flags
    Private mNWSelected As Boolean = False
    Private mNESelected As Boolean = False
    Private mSWSelected As Boolean = False
    Private mSESelected As Boolean = False

    'The way the control is coorodinated
    ' 
    'NWx,NWy                    NEx,NEy
    '   |--------------------------|
    '   |                          |
    '   |                          |
    '   |                          |
    '   |--------------------------|
    'SWx,SWy                    SEx,SEy

    'Individual offset variables
    Private mNWxOffset As Integer
    Private mNWyOffset As Integer
    Private mNExOffset As Integer
    Private mNEyOffset As Integer
    Private mSExOffset As Integer
    Private mSEyOffset As Integer
    Private mSWxOffset As Integer
    Private mSWyOffset As Integer
    Private mCenteralXOffset As Integer
    Private mCentralYOffset As Integer

    'point of the control oposite where the user is dragging
    Private storedOposite As Point

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        'Draw each of the hotspots when the form paints
        mNWRect = New Rectangle(0, 0, 10, 10)
        mNERect = New Rectangle(MyBase.Width - 11, 0, 10, 10)
        mSWRect = New Rectangle(0, MyBase.Height - 11, 10, 10)
        mSERect = New Rectangle(MyBase.Width - 11, MyBase.Height - 11, 10, 10)

        e.Graphics.DrawRectangle(Pens.Black, mNWRect)
        e.Graphics.DrawRectangle(Pens.Black, mNERect)
        e.Graphics.DrawRectangle(Pens.Black, mSWRect)
        e.Graphics.DrawRectangle(Pens.Black, mSERect)

    End Sub

    Private Sub UserControl1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown

        MyBase.Parent.SuspendLayout()

        'When the user presses down on the left mouse button store 
        'some critical numbers for use durring the mouse move.
        If (mNWRect.Contains(e.Location)) Then
            mNWSelected = True
            mNWxOffset = e.X
            mNWyOffset = e.Y
            storedOposite.X = (MyBase.Location.X + MyBase.Width)
            storedOposite.Y = (MyBase.Location.Y + MyBase.Height)

        ElseIf (mNERect.Contains(e.Location)) Then
            mNESelected = True
            mNExOffset = (MyBase.Width - e.X)
            mNEyOffset = e.Y
            storedOposite.X = MyBase.Location.X
            storedOposite.Y = (MyBase.Location.Y + MyBase.Height)

        ElseIf (mSWRect.Contains(e.Location)) Then
            mSWSelected = True
            mSWxOffset = e.X
            mSWyOffset = (MyBase.Height - e.Y)
            storedOposite.X = (MyBase.Location.X + MyBase.Width)
            storedOposite.Y = MyBase.Location.Y

        ElseIf (mSERect.Contains(e.Location)) Then
            mSESelected = True
            mSExOffset = (MyBase.Width - e.X)
            mSEyOffset = (MyBase.Height - e.Y)

        Else 'clicked on anyting BUT the handles
            mCenteralXOffset = e.X
            mCentralYOffset = e.Y

        End If

    End Sub

    Private Sub UserControl1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp

        mNWSelected = False
        mNESelected = False
        mSWSelected = False
        mSESelected = False
        MyBase.Parent.ResumeLayout()

    End Sub

    Private Sub UserControl1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove

        'Set the proper mouse pointer for each hotspot
        If (mNWRect.Contains(e.Location)) Then
            MyBase.Cursor = Cursors.PanNW

        ElseIf (mNERect.Contains(e.Location)) Then
            MyBase.Cursor = Cursors.PanNE

        ElseIf (mSWRect.Contains(e.Location)) Then
            MyBase.Cursor = Cursors.PanSW

        ElseIf (mSERect.Contains(e.Location)) Then
            MyBase.Cursor = Cursors.PanSE

        Else
            MyBase.Cursor = Cursors.SizeAll

        End If

        'React to the movement only when the left button is held down.
        If (e.Button = Windows.Forms.MouseButtons.Left) Then
            If (mNWSelected = True) Then
                Dim clientPosition As Point = MyBase.Parent.PointToClient(System.Windows.Forms.Cursor.Position)
                Dim adjustedLocation As New Point(clientPosition.X - mNWxOffset, clientPosition.Y - mNWyOffset)
                Dim width As Integer = storedOposite.X - adjustedLocation.X
                Dim height As Integer = storedOposite.Y - adjustedLocation.Y

                If ((width > 25) And (height > 25)) Then
                    MyBase.Location = adjustedLocation
                    MyBase.Width = width
                    MyBase.Height = height

                    MyBase.Invalidate()

                End If

            ElseIf (mNESelected = True) Then
                Dim clientPosition As Point = MyBase.Parent.PointToClient(System.Windows.Forms.Cursor.Position)
                Dim adjustedLocation As New Point(MyBase.Location.X, (clientPosition.Y - mNEyOffset))
                Dim width As Integer = ((clientPosition.X + mNExOffset) - MyBase.Location.X)
                Dim height As Integer = (storedOposite.Y - adjustedLocation.Y)

                If ((width > 25) And (height > 25)) Then
                    MyBase.Location = adjustedLocation
                    MyBase.Width = width
                    MyBase.Height = height

                    MyBase.Invalidate()

                End If

            ElseIf (mSWSelected = True) Then
                Dim clientPosition As Point = MyBase.Parent.PointToClient(System.Windows.Forms.Cursor.Position)
                Dim adjustedLocation As New Point(clientPosition.X - mSWxOffset, MyBase.Location.Y)
                Dim width As Integer = ((storedOposite.X + mSWxOffset) - clientPosition.X)
                Dim height As Integer = ((clientPosition.Y + mSWyOffset) - MyBase.Location.Y)

                If ((width > 25) And (height > 25)) Then
                    MyBase.Location = adjustedLocation
                    MyBase.Width = width
                    MyBase.Height = height

                    MyBase.Invalidate()

                End If

            ElseIf (mSESelected = True) Then
                Dim width As Integer = (e.X + mSExOffset)
                Dim height As Integer = (e.Y + mSEyOffset)

                If ((width > 25) And (height > 25)) Then
                    MyBase.Width = width
                    MyBase.Height = height

                    MyBase.Invalidate()

                End If

            Else
                Dim clientPosition As Point = MyBase.Parent.PointToClient(System.Windows.Forms.Cursor.Position)
                Dim adjustedLocation As New Point(clientPosition.X - mCenteralXOffset, clientPosition.Y - mCentralYOffset)
                MyBase.Location = adjustedLocation

            End If

        End If

    End Sub

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer (Senior)
United States United States
Ray spends his time between running a private software company (www.enterprocity.com) and working during the day as a Software Architect for Independent Health (www.independenthealth.com).

His second love, falling only below his wife and child, is programming. His language of choice is VB.NET but he can work in C# and C/C++ enough to get by. Unfortunately his current day job @ IH has him buried deep in solutions using Java (UGH).

He has also recently started a teaching career at a local community college.

Comments and Discussions