.net 如何处理System.Drawing形状上的单击事件

.net 如何处理System.Drawing形状上的单击事件,.net,vb.net,winforms,visual-studio,.net-4.0,.net,Vb.net,Winforms,Visual Studio,.net 4.0,我一直试图在winforms vb.net应用程序中获得以下结果 此图像中的每个圆弧或圆都可以单击, 可点击的弧以粉红色显示 我成功地编写了以下代码 Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint 'Create pen objects Dim p As New Pen(Col

我一直试图在winforms vb.net应用程序中获得以下结果

此图像中的每个圆弧或圆都可以单击, 可点击的弧以粉红色显示

我成功地编写了以下代码

Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

    'Create pen objects 
    Dim p As New Pen(Color.Green, 30)
    Dim p1 As New Pen(Color.Yellow, 30)
    Dim p2 As New Pen(Color.Red, 30)
    Dim p3 As New Pen(Color.Blue, 30)

    'Create rectangle objects 
    Dim rt As New Rectangle(160, 150, 80, 100)
    Dim rt1 As New Rectangle(100, 150, 80, 100)
    Dim rt2 As New Rectangle(130, 120, 80, 100)
    Dim rt3 As New Rectangle(130, 180, 80, 100)

    'Draw arcs 
    e.Graphics.DrawArc(p, rt, 45, -90)
    e.Graphics.DrawArc(p1, rt1, -135, -90)
    e.Graphics.DrawArc(p2, rt2, -45, -90)
    e.Graphics.DrawArc(p3, rt3, 135, -90)

End Sub
这导致了以下输出

我没想到的是:

1-如何为每个圆弧创建边框

2-如何处理每个圆弧上的单击

还有什么比我现在努力完成这件事更好的方法吗


任何帮助都将不胜感激。

特别感谢Reza Aghaei的帮助, 我在解决方案中使用了以下代码

编辑:改进答案

处理图形路径,使代码更整洁

Imports System.Drawing.Drawing2D
Public Class SurfaceSelection

Private Sub SurfaceSelection_Click(sender As Object, e As MouseEventArgs) Handles Me.Click
    Dim hitSurface As String = String.Empty
    If GetPath(EnumsClass.SurfacesEnum.L).IsVisible(e.Location) Then
        hitSurface = "L"
    ElseIf GetPath(EnumsClass.SurfacesEnum.M).IsVisible(e.Location) Then
        hitSurface = "M"
    ElseIf GetPath(EnumsClass.SurfacesEnum.F).IsVisible(e.Location) Then
        hitSurface = "F"
    ElseIf GetPath(EnumsClass.SurfacesEnum.D).IsVisible(e.Location) Then
        hitSurface = "D"
    Else
        hitSurface = "Missed"
    End If

    MsgBox(hitSurface)

End Sub

Private Sub SurfaceSelection_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

    Me.DrawPath(EnumsClass.SurfacesEnum.L, e)
    Me.DrawPath(EnumsClass.SurfacesEnum.M, e)
    Me.DrawPath(EnumsClass.SurfacesEnum.F, e)
    Me.DrawPath(EnumsClass.SurfacesEnum.D, e)

End Sub

Private Sub DrawPath(ByVal v_bytSurface As EnumsClass.SurfacesEnum, ByVal e As System.Windows.Forms.PaintEventArgs)
    Using p As GraphicsPath = GetPath(v_bytSurface)
        e.Graphics.FillPath(Brushes.Green, p)
        e.Graphics.DrawPath(Pens.Black, p)
    End Using
End Sub

Private Function GetPath(ByVal v_bytSurface As EnumsClass.SurfacesEnum) As GraphicsPath
    Dim path As New GraphicsPath
    Dim center = New Point(100, 100)
    Dim innerR = 70
    Dim thickness = 20
    Dim startAngle = getGraphicsPathAngle(v_bytSurface)
    Dim arcLength = 70
    Dim outerR = innerR + thickness
    Dim outerRect = New Rectangle(center.X - outerR, center.Y - outerR, 2 * outerR, 2 * outerR)
    Dim innerRect = New Rectangle(center.X - innerR, center.Y - innerR, 2 * innerR, 2 * innerR)
    path.AddArc(outerRect, startAngle, arcLength)
    path.AddArc(innerRect, startAngle + arcLength, -arcLength)
    path.CloseFigure()
    Return path
End Function

Private Function getGraphicsPathAngle(ByVal v_bytSurface As EnumsClass.SurfacesEnum) As Integer
    Select Case v_bytSurface
        Case EnumsClass.SurfacesEnum.F
            Return 235
        Case EnumsClass.SurfacesEnum.O
            Return 0
        Case EnumsClass.SurfacesEnum.L
            Return 55
        Case EnumsClass.SurfacesEnum.M
            Return 145
        Case EnumsClass.SurfacesEnum.D
            Return 325
        Case EnumsClass.SurfacesEnum.Unspecified
            Return -1

    End Select

End Function

End Class

Public Class EnumsClass
    Public Enum SurfacesEnum As Byte
        Unspecified = 0
        F = 1
        O = 2
        L = 3
        M = 4
        D = 5
    End Enum
End Class
我在以下问题中使用了Reza的答案:


否您不能使用
矩形。包含弧的
。你应该使用。以这篇文章为例:。也看看这篇文章来画那些弧。您只需创建一个类,其中包含绘制和点击测试对象所需的信息,一个
矩形
属性,以及
StartAngle
EndAngle
的两个整数属性。然后,您可以简单地进行命中测试和绘图。对于绘制,接受
Graphics
对象作为
Draw
方法的参数,并在其上绘制路径。绘制事件仅在需要时才会引发。当窗体需要重新绘制时,例如从“最小化”还原窗体时,或在窗体上移动另一个窗口时。你不需要对此做任何事情。只需将
DoubleBuffered=true
设置为无闪烁绘制。事实上,您无需向上投票此评论,转到问题页面,单击问题和答案附近的向上箭头:)和。我可以将其作为第一篇文章的副本关闭。你也可以根据链接的帖子发布你自己的答案。您更喜欢什么?顺便说一下,答案有内存泄漏。您正在绘制事件中反复创建一些
GraphicsPath
。您应该只创建一次。如果您一次又一次地创建它们而不处理它们,您将收到一些异常,甚至会在创建windows句柄时遇到一些问题。你应该解决这个问题!是的,您可以清除它,但应该释放GDI资源,清除和释放不同。例如,您可以在表单级别中存储它们,而只是将主题放在方法中的“使用块”中。现在没事了:)