0

I'm using Winforms with a picturebox and a custom rectangle drawn on it (face detection). Now I have code the draws the rectangle on the specified coordinates, allows resizing and moving of the recangle. However.. I need to know how to rotate the rectangle by using the MOUSE. I know how to transform it.. but to do it by using the mouse.. can someone please assist with this. Heres the code for the custom rectangle. The resize and move works fine, I need to know how to make it rotate with mouse move

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Public Class UserRect
    Private Enum PosSizableRect
        UpMiddle
        LeftMiddle
        LeftBottom
        LeftUp
        RightUp
        RightMiddle
        RightBottom
        BottomMiddle
        None
    End Enum

    Private mPictureBox As PictureBox

    Public rect As Rectangle

    Public allowDeformingDuringMovement As Boolean

    Private mIsClick As Boolean

    Private mMove As Boolean

    Private oldX As Integer

    Private oldY As Integer

    Private sizeNodeRect As Integer = 5

    Private mBmp As Bitmap

    Private nodeSelected As UserRect.PosSizableRect = UserRect.PosSizableRect.None

    Private angle As Integer = 30

    Public Sub New(r As Rectangle)
        Me.rect = r
        Me.mIsClick = False
    End Sub

    Public Sub Draw(g As Graphics)
        g.DrawRectangle(New Pen(Color.Red), Me.rect)
        For Each p As UserRect.PosSizableRect In [Enum].GetValues(GetType(UserRect.PosSizableRect))
            g.DrawRectangle(New Pen(Color.Red), Me.GetRect(p))
        Next
    End Sub

    Public Sub SetBitmapFile(filename As String)
        Me.mBmp = New Bitmap(filename)
    End Sub

    Public Sub SetBitmap(bmp As Bitmap)
        Me.mBmp = bmp
    End Sub

    Public Sub SetPictureBox(p As PictureBox)
        Me.mPictureBox = p
        AddHandler Me.mPictureBox.MouseDown, AddressOf Me.mPictureBox_MouseDown
        AddHandler Me.mPictureBox.MouseUp, AddressOf Me.mPictureBox_MouseUp
        AddHandler Me.mPictureBox.MouseMove, AddressOf Me.mPictureBox_MouseMove
        AddHandler Me.mPictureBox.Paint, AddressOf Me.mPictureBox_Paint
    End Sub

    Private Sub mPictureBox_Paint(sender As Object, e As PaintEventArgs)
        Try
            Me.Draw(e.Graphics)
        Catch ex As Exception
            Console.WriteLine(ex.Message)
        End Try
    End Sub

    Private Sub mPictureBox_MouseDown(sender As Object, e As MouseEventArgs)
        Me.mIsClick = True
        Me.nodeSelected = UserRect.PosSizableRect.None
        Me.nodeSelected = Me.GetNodeSelectable(e.Location)
        If Me.rect.Contains(New Point(e.X, e.Y)) Then
            Me.mMove = True
        End If
        Me.oldX = e.X
        Me.oldY = e.Y
    End Sub

    Private Sub mPictureBox_MouseUp(sender As Object, e As MouseEventArgs)
        Me.mIsClick = False
        Me.mMove = False
    End Sub

    Private Sub mPictureBox_MouseMove(sender As Object, e As MouseEventArgs)
        Me.ChangeCursor(e.Location)
        If Not Me.mIsClick Then
            Return
        End If
        Dim rectangle As Rectangle = Me.rect
        Select Case Me.nodeSelected
            Case UserRect.PosSizableRect.UpMiddle
                Me.rect.Y = Me.rect.Y + (e.Y - Me.oldY)
                Me.rect.Height = Me.rect.Height - (e.Y - Me.oldY)
            Case UserRect.PosSizableRect.LeftMiddle
                Me.rect.X = Me.rect.X + (e.X - Me.oldX)
                Me.rect.Width = Me.rect.Width - (e.X - Me.oldX)
            Case UserRect.PosSizableRect.LeftBottom
                Me.rect.Width = Me.rect.Width - (e.X - Me.oldX)
                Me.rect.X = Me.rect.X + (e.X - Me.oldX)
                Me.rect.Height = Me.rect.Height + (e.Y - Me.oldY)
            Case UserRect.PosSizableRect.LeftUp
                Me.rect.X = Me.rect.X + (e.X - Me.oldX)
                Me.rect.Width = Me.rect.Width - (e.X - Me.oldX)
                Me.rect.Y = Me.rect.Y + (e.Y - Me.oldY)
                Me.rect.Height = Me.rect.Height - (e.Y - Me.oldY)
            Case UserRect.PosSizableRect.RightUp
                Me.rect.Width = Me.rect.Width + (e.X - Me.oldX)
                Me.rect.Y = Me.rect.Y + (e.Y - Me.oldY)
                Me.rect.Height = Me.rect.Height - (e.Y - Me.oldY)
            Case UserRect.PosSizableRect.RightMiddle
                Me.rect.Width = Me.rect.Width + (e.X - Me.oldX)
            Case UserRect.PosSizableRect.RightBottom
                Me.rect.Width = Me.rect.Width + (e.X - Me.oldX)
                Me.rect.Height = Me.rect.Height + (e.Y - Me.oldY)
            Case UserRect.PosSizableRect.BottomMiddle
                Me.rect.Height = Me.rect.Height + (e.Y - Me.oldY)
            Case Else
                If Me.mMove Then
                    Me.rect.X = Me.rect.X + e.X - Me.oldX
                    Me.rect.Y = Me.rect.Y + e.Y - Me.oldY
                End If
        End Select
        Me.oldX = e.X
        Me.oldY = e.Y
        If Me.rect.Width < 5 OrElse Me.rect.Height < 5 Then
            Me.rect = rectangle
        End If
        Me.TestIfRectInsideArea()
        Me.mPictureBox.Invalidate()
    End Sub

    Private Sub TestIfRectInsideArea()
        If Me.rect.X < 0 Then
            Me.rect.X = 0
        End If
        If Me.rect.Y < 0 Then
            Me.rect.Y = 0
        End If
        If Me.rect.Width <= 0 Then
            Me.rect.Width = 1
        End If
        If Me.rect.Height <= 0 Then
            Me.rect.Height = 1
        End If
        If Me.rect.X + Me.rect.Width > Me.mPictureBox.Width Then
            Me.rect.Width = Me.mPictureBox.Width - Me.rect.X - 1
            If Not Me.allowDeformingDuringMovement Then
                Me.mIsClick = False
            End If
        End If
        If Me.rect.Y + Me.rect.Height > Me.mPictureBox.Height Then
            Me.rect.Height = Me.mPictureBox.Height - Me.rect.Y - 1
            If Not Me.allowDeformingDuringMovement Then
                Me.mIsClick = False
            End If
        End If
    End Sub

    Private Function CreateRectSizableNode(x As Integer, y As Integer) As Rectangle
        Return New Rectangle(x - Me.sizeNodeRect / 2, y - Me.sizeNodeRect / 2, Me.sizeNodeRect, Me.sizeNodeRect)
    End Function

    Private Function GetRect(p As UserRect.PosSizableRect) As Rectangle
        Select Case p
            Case UserRect.PosSizableRect.UpMiddle
                Return Me.CreateRectSizableNode(Me.rect.X + Me.rect.Width / 2, Me.rect.Y)
            Case UserRect.PosSizableRect.LeftMiddle
                Return Me.CreateRectSizableNode(Me.rect.X, Me.rect.Y + Me.rect.Height / 2)
            Case UserRect.PosSizableRect.LeftBottom
                Return Me.CreateRectSizableNode(Me.rect.X, Me.rect.Y + Me.rect.Height)
            Case UserRect.PosSizableRect.LeftUp
                Return Me.CreateRectSizableNode(Me.rect.X, Me.rect.Y)
            Case UserRect.PosSizableRect.RightUp
                Return Me.CreateRectSizableNode(Me.rect.X + Me.rect.Width, Me.rect.Y)
            Case UserRect.PosSizableRect.RightMiddle
                Return Me.CreateRectSizableNode(Me.rect.X + Me.rect.Width, Me.rect.Y + Me.rect.Height / 2)
            Case UserRect.PosSizableRect.RightBottom
                Return Me.CreateRectSizableNode(Me.rect.X + Me.rect.Width, Me.rect.Y + Me.rect.Height)
            Case UserRect.PosSizableRect.BottomMiddle
                Return Me.CreateRectSizableNode(Me.rect.X + Me.rect.Width / 2, Me.rect.Y + Me.rect.Height)
            Case Else
                Return Nothing
        End Select
    End Function

    Private Function GetNodeSelectable(p As Point) As UserRect.PosSizableRect
        For Each posSizableRect As UserRect.PosSizableRect In [Enum].GetValues(GetType(UserRect.PosSizableRect))
            If Me.GetRect(posSizableRect).Contains(p) Then
                Return posSizableRect
            End If
        Next
        Return UserRect.PosSizableRect.None
    End Function

    Private Sub ChangeCursor(p As Point)
        Me.mPictureBox.Cursor = Me.GetCursor(Me.GetNodeSelectable(p))
    End Sub

    Private Function GetCursor(p As UserRect.PosSizableRect) As Cursor
        Select Case p
            Case UserRect.PosSizableRect.UpMiddle
                Return Cursors.SizeNS
            Case UserRect.PosSizableRect.LeftMiddle
                Return Cursors.SizeWE
            Case UserRect.PosSizableRect.LeftBottom
                Return Cursors.SizeNESW
            Case UserRect.PosSizableRect.LeftUp
                Return Cursors.SizeNWSE
            Case UserRect.PosSizableRect.RightUp
                Return Cursors.SizeNESW
            Case UserRect.PosSizableRect.RightMiddle
                Return Cursors.SizeWE
            Case UserRect.PosSizableRect.RightBottom
                Return Cursors.SizeNWSE
            Case UserRect.PosSizableRect.BottomMiddle
                Return Cursors.SizeNS
            Case Else
                Return Cursors.[Default]
        End Select
    End Function
End Class
3
Contributors
4
Replies
35
Views
6 Months
Discussion Span
Last Post by xrj
0

Here the image rotates while dragging around the center clockwise or not, although when the mouse moves horizontally the spinning slows. A workaround could be to spin just in one direction and take into account that when dragging and y=0 the image continues spinning.

rotatingRectangle.PNG

Imports System.Drawing
Imports System.Reflection
Imports System.IO

Public Class rotatingRectangle

    Dim bDrag As Boolean
    Dim oldpos As New Point(0, 0)
    Dim oldAlpha As Double = 0.0
    WithEvents bmpBlue As Bitmap
    Dim center As Point
    Dim w, h, cliW, cliH As Single
    Dim mp As Point
    Private Sub rotatingRectangle_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Try
            Dim filename As String = "viento de cizalladura.png"
            Dim _assembly As [Assembly] = [Assembly].GetExecutingAssembly
            Dim _stream As Stream = _assembly.GetManifestResourceStream("MyNameSpace." + filename)

            bmpBlue = Bitmap.FromStream(_stream)
            _stream.Close()
            w = bmpBlue.Width
            h = bmpBlue.Height
            cliW = Me.ClientRectangle.Width
            cliH = Me.ClientRectangle.Height
            center = New Point(cliW / 2, _
                              cliH / 2)
            Me.DoubleBuffered = True
        Catch ex As Exception

        End Try
    End Sub
    Private Sub bmpBlue_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        bDrag = True
    End Sub

    Private Sub bmpBlue_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        bDrag = False
    End Sub
    Private Sub bmpBlue_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
        mp = New Point(e.X, e.Y)
        Me.Refresh()
    End Sub

    Private Sub rotatingRectangle_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Try
            Dim alpha As Double
            If bDrag Then
                If oldpos.X = 0 AndAlso oldpos.Y = 0 Then
                    oldpos = New Point(mp.X - center.X, mp.Y - center.Y)
                    Exit Sub
                End If
                Dim y As Single = mp.Y - oldpos.Y
                Dim x As Single = mp.X - oldpos.X
                If mp.X < center.X Then
                    y = -y
                End If
                alpha = Math.Atan2(y, x)
                alpha += oldAlpha
                oldpos = New Point(mp.X, mp.Y)
            Else
                alpha = oldAlpha
            End If
            e.Graphics.TranslateTransform(center.X, center.Y)
            e.Graphics.RotateTransform(alpha)
            e.Graphics.DrawImage(bmpBlue, New Point(-w / 2, -h / 2))
            oldAlpha = alpha
        Catch ex As Exception

        End Try
    End Sub
End Class

Edited by xrj

0

A briefer and improved version to rotate the image:

    Private Sub rotatingRectangle_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Try
            Dim alpha As Double
            If bDrag Then
                If oldpos.X = 0 AndAlso oldpos.Y = 0 Then
                    oldpos = New Point(mp.X, mp.Y)
                    Exit Sub
                End If
                alpha = Math.Atan2(-mp.Y - center.Y, mp.X - center.X)
                alpha += oldAlpha
                oldpos = New Point(mp.X, mp.Y)
            Else
                alpha = oldAlpha
            End If
            e.Graphics.TranslateTransform(center.X, center.Y)
            e.Graphics.RotateTransform(alpha)
            e.Graphics.DrawImage(bmpBlue, New Point(-w / 2, -h / 2))
            oldAlpha = alpha
        Catch ex As Exception

        End Try
    End Sub
0

Just to rotate in both directions:

Private Sub rotatingRectangle_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    Try
        Dim alpha As Double
        Static oldSign As Int32 = -1
        Static oldSign2 As Int32 = -1
        Dim sign As Int32 = oldSign2
        oldSign2 = oldSign
        If bDrag Then
            If oldpos.X = 0 AndAlso oldpos.Y = 0 Then
                oldpos = New Point(mp.X, mp.Y)
                Exit Sub
            End If
            alpha = Math.Atan2((-mp.Y - center.Y), _
                                (mp.X - center.X))
            alpha = Math.Abs(alpha)
            If mp.X > center.X AndAlso mp.Y - oldpos.Y > 0 Then
                sign = 1
            ElseIf mp.X < center.X AndAlso mp.Y - oldpos.Y < 0 Then
                sign = 1
            ElseIf mp.X > center.X AndAlso mp.Y - oldpos.Y < 0 Then
                sign = -1
            ElseIf mp.X < center.X AndAlso mp.Y - oldpos.Y < 0 Then
                sign = -1
            ElseIf mp.Y - oldpos.Y Then
                sign = -1
            End If
            alpha = oldAlpha + alpha * sign
            oldpos = New Point(mp.X, mp.Y)
            oldSign = sign
        Else
            alpha = oldAlpha
        End If
        e.Graphics.TranslateTransform(center.X, center.Y)
        e.Graphics.RotateTransform(alpha)
        e.Graphics.DrawImage(bmpBlue, New Point(-w / 2, -h / 2))
        oldAlpha = alpha
    Catch ex As Exception

    End Try
End Sub
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.