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 に答える