.net 如何处理System.Drawing形状上的单击事件
我一直试图在winforms vb.net应用程序中获得以下结果 此图像中的每个圆弧或圆都可以单击, 可点击的弧以粉红色显示 我成功地编写了以下代码.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
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资源,清除和释放不同。例如,您可以在表单级别中存储它们,而只是将主题放在方法中的“使用块”中。现在没事了:)