# 版主您好：求教旋转绘图的方法，谢谢！！！

• ### 问题

• 求教下面的代码会画的图形为L形自定义控件：我想是否有方法（不重写绘图代码），把控件反方向来用（即竖线在左边，原竖线在右边），谢谢！！！

Drawing.Drawing2D.Matrix 不知是否有此功能，谢谢！！！

Dim p11 As New Point(Me.mBorderWidth / 2 + 5, 5)
Dim p21 As New Point(Me.mBorderWidth / 2 + 5, Me.Height - Me.mBorderWidth * 2 - 5)
Dim p31 As New Point(Me.Width - Me.mBorderWidth * 3, Me.Height - mPen.Width * 2 - 5)
Dim ps As Point() = {p11, p21, p31}
'   Dim vcd As Integer = mPen.Width
e.Graphics.DrawLines(mPen, ps)
If vcd < 2 Then
Dim p1112 As New Point(p11.X, 0)
Dim p3112 As New Point(p11.X - 4, p11.Y + 5)
Dim p2112 As New Point(p11.X + 4, p11.Y + 5) '
Dim ps112 As Point() = {p1112, p2112, p3112}
e.Graphics.FillPolygon(mbushs, ps112)
Dim p111 As New Point(p31.X - 5, p31.Y - 4)
Dim p311 As New Point(p31.X - 5, p31.Y + 4)
Dim p211 As New Point(p31.X + Me.mBorderWidth * 2.5, p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
Dim p1 As New Point(p11.X, 0)
Dim p2 As New Point(p11.X + 5, p11.Y + 6)
Dim p3 As New Point(p11.X + mPen.Width / 2 + 1, p11.Y + 6)
Dim p4 As New Point(p11.X + mPen.Width / 2 + 1, p31.Y - 5)
Dim p5 As New Point(p31.X - 4, p31.Y - 1)
Dim p55 As New Point(p31.X - 4, p31.Y - 5)
Dim p6 As New Point(Me.Width, p31.Y)
Dim p7 As New Point(p31.X - 4, p31.Y + 5)
Dim p8 As New Point(p31.X - 4, p31.Y + 1)
Dim p9 As New Point(p11.X - mPen.Width / 2 - 1, p31.Y + 1)
Dim p10 As New Point(p11.X - mPen.Width / 2 - 1, p11.Y + 6)
Dim p119 As New Point(0, p11.Y + 6)

Dim ps1 As Point() = {p1, p2, p3, p4, p5, p55, p6, p7, p8, p9, p10, p119}
Else
Dim p1112 As New Point(p11.X, 0)
Dim p3112 As New Point(p11.X - 1.5 * vcd, p11.Y + 2.5 * vcd)
Dim p2112 As New Point(p11.X + 1.5 * vcd, p11.Y + 2.5 * vcd) '
Dim ps112 As Point() = {p1112, p2112, p3112}
e.Graphics.FillPolygon(mbushs, ps112)
'当宽度大于4，则根据宽度来决定箭头大小，看起来较为美观
Dim p111 As New Point(p31.X, p31.Y - 2 * vcd)
Dim p311 As New Point(p31.X, p31.Y + 2 * vcd)
Dim p211 As New Point(Me.Width, p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
Dim p1 As New Point(p11.X, 0)
Dim p2 As New Point(p11.X + 1.5 * vcd, p11.Y + 2.5 * vcd)
Dim p3 As New Point(p11.X + 0.5 * vcd + 1, p11.Y + 2.5 * vcd)
Dim p4 As New Point(p11.X + 0.5 * vcd + 1, p31.Y - vcd / 2 - 1)
Dim p5 As New Point(Me.Width, p31.Y - 2 * vcd - 1)
Dim p6 As New Point(Me.Width, p31.Y)
Dim p7 As New Point(p31.X - 4, p31.Y + 2 * vcd + 1)
Dim p8 As New Point(p31.X - 4, p31.Y + vcd / 2 + 1)
Dim p9 As New Point(p11.X - 0.5 * vcd - 1, p31.Y + vcd / 2 + 1)
Dim p10 As New Point(p11.X - 0.5 * vcd - 1, p11.Y + 2.5 * vcd)
Dim p119 As New Point(0, p11.Y + 2.5 * vcd)
Dim ps1 As Point() = {p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p119}
End If
Dim m_region As New Region(m_path)
Me.Region = m_region

2012年5月9日 3:44

### 答案

• 你好，

请参考以下代码，在这里我定义了一个Bool类型的变量reserved来判断是否将控件反向，然后做相应的计算处理。

```#Region "Reserved"
Private reserved As Boolean = False
Public Property IsReserverd As Boolean
Get
Return reserved
End Get
Set(value As Boolean)
reserved = value
End Set
End Property
#End Region

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim myColor As Color
Dim mPen As New Pen(myColor)
mPen.Color = Me.ForeColor
mPen.Width = mBorderWidth
Dim mbushs As Brush = New SolidBrush(Me.ForeColor)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
'我对此处代码做了一些修改，根据reserved的值来给每个点赋相应的值
'另外，我测试的时候发现当线条小于4的时候，会出现箭头显示不全的情况，是因为线条的长度设置的有些问题，你可以在这里也加入vcd小于4的处理
Dim p11 As New Point(CInt(Math.Abs(Me.Width * IIf(reserved, 1, 0) - 10 + Me.mBorderWidth / 2)), 10)
Dim p21 As New Point(CInt(Math.Abs(Me.Width * IIf(reserved, 1, 0) - 10 + Me.mBorderWidth / 2)), Me.Height - Me.mBorderWidth * 1.5)

Dim p31 As New Point(CInt(Math.Abs(Me.Width * IIf(reserved, 0, 1) - Me.mBorderWidth * 2.5)), Me.Height - mPen.Width * 1.5)
Dim ps As Point() = {p11, p21, p31}
Dim vcd As Integer = mPen.Width
e.Graphics.DrawLines(mPen, ps)

'根据线条的宽度来画箭头
'如果线宽小于4，则为其指定箭头大小，因为宽度为1或者2的时候，箭头几乎看不到
If vcd < 4 Then
Dim p111 As New Point(p31.X, p31.Y - 6)
Dim p311 As New Point(p31.X, p31.Y + 6)
Dim p211 As New Point(p31.X + 10 * IIf(reserved, -1, 1), p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
Else
'当宽度大于4，则根据宽度来决定箭头大小，看起来较为美观
Dim p111 As New Point(p31.X, p31.Y - 1.5 * vcd)
Dim p311 As New Point(p31.X, p31.Y + 1.5 * vcd)
Dim p211 As New Point(p31.X + 2.5 * vcd * IIf(reserved, -1, 1), p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
End If
End Sub```

另外，我测试的时候，发现我上一个回复中当线条宽度小于4的时候，可能会出现箭头显示不全的情况，如果你使用了那些代码，请注意修改。

Regards,

Shanks Zen
MSDN Community Support | Feedback to us

• 已标记为答案 2012年5月10日 9:58
2012年5月10日 6:36
• 您好，

请参考以下代码，我在里面加入了另一个新的参数Solid，来决定是否显示空心的图案，代码部分略显臃肿，见谅。

```Public Class UserControl1
Public Sub New()
MyBase.New()
Me.Size = New Size(500, 500)
Me.BorderStyle = Windows.Forms.BorderStyle.None
End Sub

#Region "BorderWidth"
Private mBorderWidth As Short = 10

Public Property BorderWidth() As Short
Get
Return mBorderWidth
End Get
Set(ByVal value As Short)
mBorderWidth = value
Me.Invalidate()
End Set
End Property

#End Region
'实心空心开关
#Region "IsSolid"
Private isSolid As Boolean = False

Public Property mSolid As Boolean
Get
Return isSolid
End Get
Set(value As Boolean)
isSolid = value
End Set
End Property
#End Region
'设置空心时的线条间距
#Region "LineWidth"
Private mLineWidth As Short = 19

Public Property LineWidth() As Short
Get
Return mLineWidth
End Get
Set(ByVal value As Short)
mLineWidth = value
Me.Invalidate()
End Set
End Property
#End Region
'反向开关
#Region "Reserved"
Private reserved As Boolean = False
Public Property IsReserverd As Boolean
Get
Return reserved
End Get
Set(value As Boolean)
reserved = value
End Set
End Property
#End Region

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim myColor As Color
Dim mPen As New Pen(myColor)
mPen.Color = Me.ForeColor
mPen.Width = mBorderWidth
Dim mbushs As Brush = New SolidBrush(Me.ForeColor)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim ps As Point()
Dim vcd As Integer = mPen.Width

'加入这段是因为要判断线条宽度，和线条间距是图形显示完整
If vcd < 4 And mLineWidth < 4 Then
Me.mBorderWidth = 4
ElseIf vcd > mLineWidth Then
Else
Me.mBorderWidth = mLineWidth
End If

'我对此处坐标轴代码做了一些修改，使线条宽度较大时箭头也可以正常显示
Dim p11 As New Point(10 + Me.mBorderWidth / 2, 10)
Dim p21 As New Point(10 + Me.mBorderWidth / 2, Me.Height - Me.mBorderWidth * 1.5 - 10)
Dim p31 As New Point(Me.Width - Me.mBorderWidth * 2.5, Me.Height - Me.mBorderWidth * 1.5 - 10)
Me.mBorderWidth = mPen.Width

'如果是实体的图形，就还是和之前的代码一样了
If isSolid Then
ps = {p11, p21, p31}
e.Graphics.DrawLines(mPen, ps)
If vcd < 4 Then
Dim p111 As New Point(p31.X, p31.Y - 6)
Dim p311 As New Point(p31.X, p31.Y + 6)
Dim p211 As New Point(p31.X + 10, p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
Else
'当宽度大于4，则根据宽度来决定箭头大小，看起来较为美观
Dim p111 As New Point(p31.X, p31.Y - 1.5 * vcd)
Dim p311 As New Point(p31.X, p31.Y + 1.5 * vcd)
Dim p211 As New Point(p31.X + 2.5 * vcd, p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
End If

'如果不是实心的图形，需要多一些的运算，因为连线的点变多了，另外还需要声明一个变量来制定空心线条之间的距离。
Else
If vcd < 4 And mLineWidth < 4 Then
Me.mBorderWidth = 4
ElseIf vcd > mLineWidth Then
Else
Me.mBorderWidth = mLineWidth
End If
Dim p11s As New Point(10 + Me.mBorderWidth / 2 + LineWidth, 10)
Dim p21s As New Point(10 + Me.mBorderWidth / 2 + LineWidth, Me.Height - Me.mBorderWidth * 1.5 - LineWidth - 10)
Dim p31s As New Point(Me.Width - Me.mBorderWidth * 2.5, Me.Height - Me.mBorderWidth * 1.5 - LineWidth - 10)
Me.mBorderWidth = mPen.Width
If mLineWidth < 4 Then
Dim p111 As New Point(p31.X, p31s.Y - 6)
Dim p311 As New Point(p31.X, p31.Y + 6)
Dim p211 As New Point(p31.X + 10, p31.Y - 3) '

ps = {p11, p11s, p21s, p31s, p111, p211, p311, p31, p21, p11}
e.Graphics.DrawLines(mPen, ps)
'Dim ps11 As Point() = {p111, p211, p311}
'e.Graphics.FillPolygon(mbushs, ps11)
Else
Dim p111 As New Point(p31.X, p31s.Y - 1.5 * mLineWidth)
Dim p311 As New Point(p31.X, p31.Y + 1.5 * mLineWidth)
Dim p211 As New Point(p31.X + 2.3 * mLineWidth, p31.Y - 0.5 * mLineWidth) '
ps = {p11, p11s, p21s, p31s, p111, p211, p311, p31, p21, p11}
e.Graphics.DrawLines(mPen, ps)
End If
End If

End Sub
End Class```
Regards,

Shanks Zen
MSDN Community Support | Feedback to us

2012年5月11日 5:33

### 全部回复

• 你好，

请参考以下代码，在这里我定义了一个Bool类型的变量reserved来判断是否将控件反向，然后做相应的计算处理。

```#Region "Reserved"
Private reserved As Boolean = False
Public Property IsReserverd As Boolean
Get
Return reserved
End Get
Set(value As Boolean)
reserved = value
End Set
End Property
#End Region

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim myColor As Color
Dim mPen As New Pen(myColor)
mPen.Color = Me.ForeColor
mPen.Width = mBorderWidth
Dim mbushs As Brush = New SolidBrush(Me.ForeColor)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
'我对此处代码做了一些修改，根据reserved的值来给每个点赋相应的值
'另外，我测试的时候发现当线条小于4的时候，会出现箭头显示不全的情况，是因为线条的长度设置的有些问题，你可以在这里也加入vcd小于4的处理
Dim p11 As New Point(CInt(Math.Abs(Me.Width * IIf(reserved, 1, 0) - 10 + Me.mBorderWidth / 2)), 10)
Dim p21 As New Point(CInt(Math.Abs(Me.Width * IIf(reserved, 1, 0) - 10 + Me.mBorderWidth / 2)), Me.Height - Me.mBorderWidth * 1.5)

Dim p31 As New Point(CInt(Math.Abs(Me.Width * IIf(reserved, 0, 1) - Me.mBorderWidth * 2.5)), Me.Height - mPen.Width * 1.5)
Dim ps As Point() = {p11, p21, p31}
Dim vcd As Integer = mPen.Width
e.Graphics.DrawLines(mPen, ps)

'根据线条的宽度来画箭头
'如果线宽小于4，则为其指定箭头大小，因为宽度为1或者2的时候，箭头几乎看不到
If vcd < 4 Then
Dim p111 As New Point(p31.X, p31.Y - 6)
Dim p311 As New Point(p31.X, p31.Y + 6)
Dim p211 As New Point(p31.X + 10 * IIf(reserved, -1, 1), p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
Else
'当宽度大于4，则根据宽度来决定箭头大小，看起来较为美观
Dim p111 As New Point(p31.X, p31.Y - 1.5 * vcd)
Dim p311 As New Point(p31.X, p31.Y + 1.5 * vcd)
Dim p211 As New Point(p31.X + 2.5 * vcd * IIf(reserved, -1, 1), p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
End If
End Sub```

另外，我测试的时候，发现我上一个回复中当线条宽度小于4的时候，可能会出现箭头显示不全的情况，如果你使用了那些代码，请注意修改。

Regards,

Shanks Zen
MSDN Community Support | Feedback to us

• 已标记为答案 2012年5月10日 9:58
2012年5月10日 6:36
• 您太厉害了，谢谢！！！我以前自己琢磨写了一个股票分析系统（自己用），但我就是觉得运算速度和专业的无法相比，不知您是否有时间帮助我一下，谢谢！！！

http://www.mndsoft.com/blog/DoNet/stock2011.html

2012年5月10日 9:58
• 谢谢版主，我修改过了，谢谢！！！

还请教：

我想在控件显示时，只显示线条和箭头，其他部位为透明的，我原先用下面方式来实现的，但很麻烦，可用了你的却不知如何做了，还请教您，谢谢！！！

Dim m_path As Drawing2D.GraphicsPath
m_path = New Drawing2D.GraphicsPath(Drawing2D.FillMode.Winding)

Dim p1 As New Point(p11.X, 0)
Dim p2 As New Point(p11.X + 5, p11.Y + 6)
Dim p3 As New Point(p11.X + mPen.Width / 2 + 1, p11.Y + 6)
Dim p4 As New Point(p11.X + mPen.Width / 2 + 1, Me.Height - mPen.Width - 1)
Dim p5 As New Point(Me.Width, Me.Height - mPen.Width - 1)
Dim p6 As New Point(Me.Width, Me.Height)
Dim p7 As New Point(p11.X - 5, Me.Height)
Dim p8 As New Point(p11.X - 5, p11.Y + 6)
Dim p9 As New Point(0, p11.Y + 5)
Dim ps1 As Point() = {p1, p2, p3, p4, p5, p6, p7, p8, p9}
Dim m_region As New Region(m_path)
Me.Region = m_region

2012年5月10日 11:16
• 您好，

请参考以下代码，我在里面加入了另一个新的参数Solid，来决定是否显示空心的图案，代码部分略显臃肿，见谅。

```Public Class UserControl1
Public Sub New()
MyBase.New()
Me.Size = New Size(500, 500)
Me.BorderStyle = Windows.Forms.BorderStyle.None
End Sub

#Region "BorderWidth"
Private mBorderWidth As Short = 10

Public Property BorderWidth() As Short
Get
Return mBorderWidth
End Get
Set(ByVal value As Short)
mBorderWidth = value
Me.Invalidate()
End Set
End Property

#End Region
'实心空心开关
#Region "IsSolid"
Private isSolid As Boolean = False

Public Property mSolid As Boolean
Get
Return isSolid
End Get
Set(value As Boolean)
isSolid = value
End Set
End Property
#End Region
'设置空心时的线条间距
#Region "LineWidth"
Private mLineWidth As Short = 19

Public Property LineWidth() As Short
Get
Return mLineWidth
End Get
Set(ByVal value As Short)
mLineWidth = value
Me.Invalidate()
End Set
End Property
#End Region
'反向开关
#Region "Reserved"
Private reserved As Boolean = False
Public Property IsReserverd As Boolean
Get
Return reserved
End Get
Set(value As Boolean)
reserved = value
End Set
End Property
#End Region

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim myColor As Color
Dim mPen As New Pen(myColor)
mPen.Color = Me.ForeColor
mPen.Width = mBorderWidth
Dim mbushs As Brush = New SolidBrush(Me.ForeColor)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim ps As Point()
Dim vcd As Integer = mPen.Width

'加入这段是因为要判断线条宽度，和线条间距是图形显示完整
If vcd < 4 And mLineWidth < 4 Then
Me.mBorderWidth = 4
ElseIf vcd > mLineWidth Then
Else
Me.mBorderWidth = mLineWidth
End If

'我对此处坐标轴代码做了一些修改，使线条宽度较大时箭头也可以正常显示
Dim p11 As New Point(10 + Me.mBorderWidth / 2, 10)
Dim p21 As New Point(10 + Me.mBorderWidth / 2, Me.Height - Me.mBorderWidth * 1.5 - 10)
Dim p31 As New Point(Me.Width - Me.mBorderWidth * 2.5, Me.Height - Me.mBorderWidth * 1.5 - 10)
Me.mBorderWidth = mPen.Width

'如果是实体的图形，就还是和之前的代码一样了
If isSolid Then
ps = {p11, p21, p31}
e.Graphics.DrawLines(mPen, ps)
If vcd < 4 Then
Dim p111 As New Point(p31.X, p31.Y - 6)
Dim p311 As New Point(p31.X, p31.Y + 6)
Dim p211 As New Point(p31.X + 10, p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
Else
'当宽度大于4，则根据宽度来决定箭头大小，看起来较为美观
Dim p111 As New Point(p31.X, p31.Y - 1.5 * vcd)
Dim p311 As New Point(p31.X, p31.Y + 1.5 * vcd)
Dim p211 As New Point(p31.X + 2.5 * vcd, p31.Y) '
Dim ps11 As Point() = {p111, p211, p311}
e.Graphics.FillPolygon(mbushs, ps11)
End If

'如果不是实心的图形，需要多一些的运算，因为连线的点变多了，另外还需要声明一个变量来制定空心线条之间的距离。
Else
If vcd < 4 And mLineWidth < 4 Then
Me.mBorderWidth = 4
ElseIf vcd > mLineWidth Then
Else
Me.mBorderWidth = mLineWidth
End If
Dim p11s As New Point(10 + Me.mBorderWidth / 2 + LineWidth, 10)
Dim p21s As New Point(10 + Me.mBorderWidth / 2 + LineWidth, Me.Height - Me.mBorderWidth * 1.5 - LineWidth - 10)
Dim p31s As New Point(Me.Width - Me.mBorderWidth * 2.5, Me.Height - Me.mBorderWidth * 1.5 - LineWidth - 10)
Me.mBorderWidth = mPen.Width
If mLineWidth < 4 Then
Dim p111 As New Point(p31.X, p31s.Y - 6)
Dim p311 As New Point(p31.X, p31.Y + 6)
Dim p211 As New Point(p31.X + 10, p31.Y - 3) '

ps = {p11, p11s, p21s, p31s, p111, p211, p311, p31, p21, p11}
e.Graphics.DrawLines(mPen, ps)
'Dim ps11 As Point() = {p111, p211, p311}
'e.Graphics.FillPolygon(mbushs, ps11)
Else
Dim p111 As New Point(p31.X, p31s.Y - 1.5 * mLineWidth)
Dim p311 As New Point(p31.X, p31.Y + 1.5 * mLineWidth)
Dim p211 As New Point(p31.X + 2.3 * mLineWidth, p31.Y - 0.5 * mLineWidth) '
ps = {p11, p11s, p21s, p31s, p111, p211, p311, p31, p21, p11}
e.Graphics.DrawLines(mPen, ps)
End If
End If

End Sub
End Class```
Regards,

Shanks Zen
MSDN Community Support | Feedback to us

2012年5月11日 5:33
• 谢谢您的帮助！！！谢谢！！！
2012年5月13日 21:27