0

我正在使用带有 PictureBox 和在其上绘制的自定义矩形(人脸检测)的 WinForms。现在我有了在指定坐标上绘制矩形并允许调整矩形大小和移动矩形的代码。但是,我需要知道如何使用鼠标旋转矩形。我知道如何转换它,但不知道如何使用鼠标进行转换。有人可以帮忙吗?

这是自定义矩形的代码:

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
4

1 回答 1

1

这是场景:当用户第一次按下鼠标时,检查例如CTRL键是否也被按下ModifierKeys = Keys.Control然后我们应该开始旋转(CTRL键用于区分移动和旋转)。为此,我们应该知道旋转中心以及旋转量(旋转角度)。我们可以假设矩形(面)的中心是我们的旋转中心。要找到旋转角度,我们应该做一些计算:

Dim a1, a2, delta as Double
a1 = Math.Atan2(yA-yO, xA-xO)
a2 = Math.Atan2(yB-yO, xB-xO)
delta = a2 - a1 'this is the angle AOB (in radians) to be applied for rotation to all 4 points 

在此处输入图像描述

于 2016-12-18T11:40:05.527 回答