我有一个程序,我可以用鼠标在四个方向中的任何一个方向绘制一个矩形。
这些矩形在图片框上用于裁剪图像的一部分。
绘制这些矩形时必须保持给定尺寸的比例,例如 320 x 200。
我希望这个工具的行为与 Photoshop 中的裁剪工具非常相似,或者像此处的裁剪示例一样: https://imageresize.org/
我的大多数元素都工作正常,我只是在一些几何计算上遇到困难。
请参阅我的代码中的“右下角”示例。这非常有效,基本上我只想将这个精确的公式应用到其他方向。
我已经玩了几个小时不同的计算,但我似乎无法解决。
这是工作代码:
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
'Draw rectangle keeping aspect ratio
If e.Button = Windows.Forms.MouseButtons.Left Then
If e.X > startPos.X And e.Y > startPos.Y Then
'Bottom right
mRect = New Rectangle(mRect.Left, mRect.Top, e.X - mRect.Left, e.Y - mRect.Top)
mRect.Size = New Size(mRect.Width, mRect.Width / Ratio.Text)
If e.Y < mRect.Bottom Then
mRect = Rectangle.FromLTRB(startPos.X, startPos.Y, e.X, e.Y)
mRect.Size = New Size(mRect.Height * Ratio.Text, mRect.Height)
End If
Me.Invalidate()
ElseIf e.X < startPos.X And e.Y > startPos.Y Then
'Bottom left
mRect = New Rectangle(e.X, startPos.Y, startPos.X - e.X, e.Y - startPos.Y)
mRect.Size = New Size(mRect.Width, mRect.Width / Ratio.Text)
Me.Invalidate()
ElseIf e.X > startPos.X And e.Y < startPos.Y Then
'Top right
mRect = New Rectangle(startPos.X, e.Y, e.X - startPos.X, startPos.Y - e.Y)
mRect.Size = New Size(mRect.Height * 1.6, mRect.Height)
Me.Invalidate()
ElseIf e.X < startPos.X And e.Y < startPos.Y Then
'Top left
mRect = New Rectangle(e.X, e.Y, startPos.X - e.X, startPos.Y - e.Y)
mRect.Size = New Size(mRect.Width, mRect.Width / Ratio.Text)
Me.Invalidate()
End If
End If
End Sub
任何帮助将不胜感激。谢谢!
以下是目前的工作方式,您可以看到在西北地区绘图时事情变得很有趣。我需要为所有象限获得与东南部(或代码右下角)相同的行为。
最佳答案
当将比率应用于矩形尺寸时,我提出了一种稍微不同的方法来计算光标的当前位置。
您当然需要使用控件的 MouseDown 事件保存矩形的起始位置,然后使用 MouseMove 事件跟踪鼠标移动。
光标的当前位置照常计算(当偏移量为负时,交换当前光标位置和起始位置)。
当整体大小受到比率约束时,唯一的区别是矩形的高度。
在这种情况下,Rectangle.Location.Y
由 Rectangle.Width / Ratio
确定测量。如果 Cursor.Location.Y
则这变得可见 位于起始位置 ( Cursor.Location.Y <= StartingPosition.Y
) 之上。就像您发布的代码一样。
例如,我使用一个自定义 Rectangle 类,该类包含绘制形状所需的所有信息,无论是否对其尺寸应用了特定的比率。
▶ 请注意Ratio
被硬编码为 1.6
:这只是为了测试,当然可以设置为其他值。
结果的可视化示例:
Private DrawingRects As List(Of DrawingRectangle) = New List(Of DrawingRectangle)()
Private Sub PicureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PicureBox1.MouseDown
If e.Button = MouseButtons.Left Then
DrawingRects.Add(New DrawingRectangle() With {
.DrawingcColor = Color.LightGreen,
.Location = e.Location,
.Owner = CType(sender, Control),
.Ratio = 1.6,
.Size = Size.Empty,
.StartPosition = e.Location
})
End If
End Sub
Private Sub PicureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PicureBox1.MouseMove
If e.Button = MouseButtons.Left Then
Dim rect As DrawingRectangle = DrawingRects.Last()
If e.X < rect.StartPosition.X Then rect.Location = New Point(e.X, rect.Location.Y)
If e.Y < rect.StartPosition.Y Then rect.Location = New Point(rect.Location.X, e.Y)
Dim currentWidth As Integer = Math.Abs(rect.StartPosition.X - e.X)
If rect.Ratio = 1.0F Then
rect.Size = New Size(currentWidth, Math.Abs(rect.StartPosition.Y - e.Y))
Else
If rect.StartPosition.Y <= rect.Location.Y Then
rect.Size = New Size(currentWidth, CType(Math.Abs(rect.StartPosition.X - e.X) / rect.Ratio, Integer))
Else
Dim currentHeight As Integer = CType(currentWidth / rect.Ratio, Integer)
rect.Location = New Point(rect.Location.X, rect.StartPosition.Y - currentHeight)
rect.Size = New Size(currentWidth, currentHeight)
End If
End If
DrawingRects(DrawingRects.Count - 1) = rect
DirectCast(sender, Control).Invalidate()
End If
End Sub
Private Sub PicureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PicureBox1.Paint
Dim canvas As Control = DirectCast(sender, Control)
If DrawingRects.Count > 0 Then
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
For Each rect As DrawingRectangle In DrawingRects
If canvas IsNot rect.Owner Then Continue For
Using pen As New Pen(rect.DrawingcColor, rect.PenSize)
e.Graphics.DrawRectangle(pen, New Rectangle(rect.Location, rect.Size))
End Using
Next
End If
End Sub
DrawingRectangle
类:
▶ 注意:该类有一个 Owner
属性,引用绘制形状的当前 Control:这允许使用 List(Of DrawingRectangle)
同时使用不同的控件。
Public Class DrawingRectangle
Private rectAspect As SizeF = SizeF.Empty
Private rectRatio As Single = 0F
Public Property Owner As Control
Public Property Location As Point
Public Property Size As Size
Public Property StartPosition As Point
Public Property DrawingcColor As Color
Public Property PenSize As Single
Public Property Aspect() As SizeF
Get
Return rectAspect
End Get
Set(ByVal value As SizeF)
Me.rectAspect = value
SetAspectRatio(value)
End Set
End Property
Public Property Ratio As Single
Get
Return rectRatio
End Get
Set(ByVal value As Single)
rectRatio = value
SetAspectRatio(value)
End Set
End Property
Private Sub SetAspectRatio(aspect As SizeF)
Me.rectRatio = aspect.Width / aspect.Height
End Sub
Private Sub SetAspectRatio(ratio As Single)
Me.rectAspect = New SizeF(100, 100 / ratio)
End Sub
End Class
关于vb.net - 使用比例绘制和缩放矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54703035/