GDI+ 中调整和旋转形状






4.97/5 (12投票s)
绘制一个类似形状的编辑器,实现使用锚点来调整和旋转选定矩形的功能
引言
该代码实现了一个鼠标驱动的形状编辑器,支持通过锚点移动、调整大小和旋转选定矩形,这些锚点可用于轮廓显示任何类型的内容,例如图像、形状、文本等。
背景
在 GDI+ 中绘制旋转元素是一项相当简单的任务。通过鼠标移动创建调整大小机制也很简单。当您尝试调整旋转元素的大小时,可能会出现一些问题,这是由于 GDI+ 允许您围绕给定点(通常是中心)旋转形状的方式造成的。
经过许多天令人沮丧的 Google 搜索,我提出了这个解决方案,并在此分享,希望能帮助您节省时间。
Using the Code
窗体的 mouse_
事件显示了如何处理鼠标移动以及如何检测正在执行的操作类型(move
、resize
、rotate
)。
所有绘图都发生在 Render
方法中,该方法还负责存储用于鼠标事件的区域,以检测鼠标的位置和使用方式。
在处理旋转对象时,需要通过区域(或路径)进行鼠标命中测试,以便正确地将光标位置与屏幕上的元素关联起来。
在调整旋转元素的大小时,**关键是选择正确的中心原点进行旋转**,即在调整大小开始之前最后一次渲染矩形时的中心。
' Define center origin
Dim ptCenter As PointF = _
New PointF(_rcRect.Left + (_rcRect.Width / 2), _rcRect.Top + (_rcRect.Height / 2))
' Check for on-going resize operation
Select Case _eMouseOperation
Case MouseOperation.Nwse To MouseOperation.We
' Use last known center origin
ptCenter = _ptCenter
Case Else
_ptCenter = ptCenter
End Select
此外,在渲染旋转元素后,需要计算矩形在平坦状态下的位置,围绕新的中心原点进行计算。这将是调整大小操作完成后要使用的新的矩形。
' Check for rotation
If (_rgRect IsNot Nothing) AndAlso (_snAngle <> 0.0) Then
' Get rotatetd rectangle bounds
Dim rfNewBounds As RectangleF = _rgRect.GetBounds(oGfx)
' Check for resize operation on a rotated element
If (_eMouseOperation >= MouseOperation.Nwse) AndAlso _eMouseOperation <= MouseOperation.We Then
' Get center origin of the region
Dim ptNewScreenCenterOrigin As New PointF_
(rfNewBounds.Left + (rfNewBounds.Width / 2), rfNewBounds.Top + (rfNewBounds.Height / 2))
' Compute a rectangle based on source rectangle size and located around the center point
' of the bounds of the rotated region
Dim rcNewRenderRect As New RectangleF((ptNewScreenCenterOrigin.X - (_rcRect.Width / 2)), _
(ptNewScreenCenterOrigin.Y - (_rcRect.Height / 2)), _
_rcRect.Width, _
_rcRect.Height)
' Store for mouse up
_rcResizeMouseUpRenderRect = rcNewRenderRect
End If
End If
关注点
AnchorToCursor
方法返回当鼠标悬停在其中一个锚点上时最合适的光标。选择会考虑到锚点类型(基本点)和当前的旋转角度。事实证明,渲染自定义旋转箭头光标可能会导致不良结果,因此最好始终使用一个工厂箭头,即使角度与旋转/基本点不完全匹配。
Microsoft Office 形状编辑器使用相同的方法。
历史
- 首次提交于 2017 年 12 月 30 日
- 已修复错误并提交于 2021 年 12 月 9 日