我正在创建一个飞镖评分程序(在我的飞镖室中使用我自己),并希望用户能够单击飞镖板图片的不同区域来注册投掷的飞镖。
这个程序可以调整大小,所以当用户改变程序窗口大小时,飞镖板的图片可以改变它的大小。
我使用多边形列表(pointF-arrays)来映射每个区域并运行一些计算以查看鼠标单击是否在多边形区域内,但是当图片框调整大小时如何正确缩放这些多边形?我的多边形经过硬编码,以特定尺寸映射图片的飞镖区域。
编辑:在 Olivier Jacot-Descombes 给出非常出色的回答之后,我使用 GetScaledPoint 函数修复了缩放,该函数将鼠标指针 x 和 y 值转换为与原始图片大小匹配的值,从而可以轻松检查原始多边形中的命中. 如果有人感兴趣,我已经在下面的代码中编辑了解决方案。在此示例中,Picture1 是飞镖板的图片(例如http://quizmasters.biz/Pub%20Genius/Darts/Gfx/Dartboard_05.jpg),设置为 sizemode=stretch 和 docking=fill。
Public Class DartBoard
Dim Double20 = New PointF() {New PointF(263, 78), New PointF(275, 76), New PointF(284, 76), New PointF(293, 75), New PointF(306, 75), New PointF(319, 75), New PointF(332, 76), New PointF(330, 89), New PointF(320, 88), New PointF(309, 87), New PointF(300, 87), New PointF(289, 88), New PointF(277, 89), New PointF(267, 91), New PointF(264, 78)}
Dim Triple20 = New PointF() {New PointF(279, 154), New PointF(285, 154), New PointF(293, 154), New PointF(301, 152), New PointF(306, 152), New PointF(312, 152), New PointF(314, 151), New PointF(322, 152), New PointF(320, 167), New PointF(312, 165), New PointF(304, 164), New PointF(297, 165), New PointF(289, 166), New PointF(281, 166), New PointF(277, 154), New PointF(283, 153), New PointF(291, 153), New PointF(299, 152), New PointF(308, 152), New PointF(314, 153), New PointF(322, 153)}
Private startwidth As Integer = 0
Private startheight As Integer = 0
Public Structure DartBoardAreaStruct
Public Points As Integer
Public Area() As PointF
End Structure
Dim DartBoardAreas As New List(Of DartBoardAreaStruct)
Private Sub DartBoard_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DartBoardAreas.Add(New DartBoardAreaStruct With {.Area = Double20, .Points = 40})
DartBoardAreas.Add(New DartBoardAreaStruct With {.Area = Triple20, .Points = 60})
startwidth = PictureBox1.Width
startheight = PictureBox1.Height
End Sub
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
Dim scaledpos As PointF = GetScaledPoint(e.Location)
For Each DartBoardArea In DartBoardAreas
If Me.PolyGonHitTest(DartBoardArea.Area, scaledpos) Then
MsgBox(DartBoardArea.Points)
End If
Next
End Sub
Public Function PolyGonHitTest(ByVal polygonPoints() As PointF, ByVal mousePos As PointF) As Boolean
Dim path As New System.Drawing.Drawing2D.GraphicsPath
path.AddLines(polygonPoints)
Dim region As New Region(path)
If region.IsVisible(mousePos) Then Return True
Return False
End Function
Function GetScaledPoint(ByVal s As Point) As PointF
Dim xfactor As Double = 0
Dim yfactor As Double = 0
Dim OriginalSize As Size = New Size(startwidth, startheight)
Dim NewSize As Size = New Size(PictureBox1.Width, PictureBox1.Height)
If NewSize.Width < OriginalSize.Width Then
xfactor = OriginalSize.Width / NewSize.Width
Else
xfactor = NewSize.Width / OriginalSize.Width
End If
If NewSize.Height < OriginalSize.Height Then
yfactor = OriginalSize.Height / NewSize.Height
Else
yfactor = NewSize.Height / OriginalSize.Height
End If
Return New PointF(s.X / xfactor, s.Y / yfactor)
End Function
End Class