CCreateArc类

CCreateArc类描述如何交互绘制圆弧。本程序采用圆心、起点和终点三点绘制圆弧,所以用鼠标交互绘图时需要确定这3个点的位置。其大体思路是:前两次单击鼠标左键分别定义圆心和起点,这两点定义以后是不会变的;然后定义圆弧的终点。终点不能直接定义,因为在绘图区我们基本上不能直接获得终点的准确位置,但可以间接得到终点坐标。具体方法是根据第3点的方位角和由前两点得到的半径,计算出终点的准确位置。所以我们说的用圆心、起点和终点绘制圆弧从本质上讲应该是用圆心、起点和第3点绘制圆弧。

与前面的CCreateLine类和CCreateCircle类一样,CCreateArc类也实现了ICommand 接口。类中用到4个局部变量,m_Step定义鼠标左键的单击次数,m_Center、m_Begin和m_End分别记录圆弧的圆心、起点和终点的坐标。

LButonDown方法实现了 Command接口的LButondown方法。第一次单击鼠标左键时,定义圆心的位置,将当前点的坐标赋给m_Center。第2次单击鼠标左键时,确定圆弧起点的位置,并将该位置也赋给m_End对象,作为终点。所以,在初始情况下,圆弧的起点和终点是重合的。然后代码中用前面定义的3个点构造了一个暂时的CArc对象,并用拖曳模式绘制了该对象,然后注销。为什么要这样做,将在介绍MouseMove方法时介绍。第3次单击鼠标左键时,清除圆心到起点的橡皮线、圆心到终点的橡皮线和橡皮弧,以正常模式绘制最后生成的圆弧。将m_Step归0。

code.vb.net
'创建圆弧类
Public Class CCreateArc
    Implements ICommand
    Private m_Step As Integer
    Private m_Center, m_Begin, m_End As PointF
    Public Sub LButtonDown(ByVal g As Graphics, ByVal aPos As PointF) Implements ICommand.LButtonDown
        '记录鼠标左键的单击次数
        m_Step += 1
        Select Case m_Step
            Case 1               '第1次单击鼠标左键
                m_Center = aPos
            Case 2
                m_Begin = aPos
                m_End = aPos
                Dim tempArc1 As New CArc(m_Center, aPos, aPos)
                tempArc1.Draw(g, CGElement.geDrawMode.Drag)
                tempArc1 = Nothing
            Case 3
                '清除最后一次拖动时圆心到起点的橡皮线
                Dim tempLine1 As New CLine(m_Center, m_Begin)
                tempLine1.Draw(g, CGElement.geDrawMode.Drag)
                tempLine1 = Nothing
                '清除最后一次拖动时圆心到终点的橡皮线
                Dim tempLine2 As New CLine(m_Center, m_End)
                tempLine2.Draw(g, CGElement.geDrawMode.Drag)
                tempLine2 = Nothing
                '清除最后一次拖动时显示的橡皮弧
                Dim tempArc As New CArc(m_Center, m_Begin, m_End)
                tempArc.Draw(g, CGElement.geDrawMode.Drag)
                tempArc = Nothing
                '绘当前位置的圆弧
                Dim newArc As New CArc(m_Center, m_Begin, aPos)
                newArc.Draw(g, CGElement.geDrawMode.Normal)
                ges.Add(newArc)
                m_Step = 0
        End Select
    End Sub
End Class

MouseMove 方法实现了ICommand接口的MouseMove方法,用于描述鼠标在绘图区移动时的绘图行为。鼠标移动时,需要不断地清除上一条圆心到终点的橡皮线、上一条橡皮弧,并绘制当前的圆心到终点的橡皮线和橡皮弧。需要注意的是,在介绍LButtonDown 方法时说过,在初始状态下,圆弧的起点和终点是重合的。既然是重合的,那么,绘出的是一个点还是一个圆呢?读者朋友不妨测试一下,结果是一个圆。但绘制橡皮弧时,首先要清除上一个橡皮弧,由于在鼠标第1次移动以前并没有绘圆弧,所以没有上一个橡皮弧可供清除。结果如何呢?由于采用拖曳模式绘制,它不但没有清除,实际上还绘了一个圆。这样,后面的橡皮弧绘制将全部反向,实际上是逆时针方向绘制的,显示在屏幕上却是顺时针方向绘制。所以,在前面的LButtonDown方法中,在第2次单击以后就根据给定的3个点以拖曳模式绘了一个圆,等着MouseMove方法来清除。当前橡皮线和橡皮弧绘制完毕以后,不要忘了将当前点设置为m_End。

code.vb.net
    Public Sub MouseMove(ByVal g As Graphics, ByVal aPos As PointF) Implements ICommand.MouseMove
        Select Case m_Step
            Case 2
                Dim prePos As New PointF()
                Dim curPos As New PointF()
                prePos = m_End
                curPos = aPos
                '清除上一条圆心到终点的橡皮线
                Dim tempLine1 As New CLine(m_Center, prePos)
                tempLine1.Draw(g, CGElement.geDrawMode.Drag)
                tempLine1 = Nothing
                '清除上一个橡皮弧
                Dim tempArc1 As New CArc(m_Center, m_Begin, prePos)
                tempArc1.Draw(g, CGElement.geDrawMode.Drag)
                tempArc1 = Nothing
                '绘当前圆心到终点的橡皮线
                Dim tempLine2 As New CLine(m_Center, curPos)
                tempLine2.Draw(g, CGElement.geDrawMode.Drag)
                tempLine2 = Nothing
                '绘当前位置的橡皮弧
                Dim tempArc2 As New CArc(m_Center, m_Begin, curPos)
                tempArc2.Draw(g, CGElement.geDrawMode.Drag)
                tempArc2 = Nothing
                m_End = curPos
        End Select
    End Sub

RButtonDown方法实现了ICommand接口的RButtonDown方法,它实现对当前未完成工作的取消。取消操作需要从屏幕上清除圆心到起点的橡皮线、圆心到终点的橡皮线和橡皮弧,并将m_Step的值设为0。

code.vb.net
    '单击鼠标右键时的绘图行为
    Public Sub RButtonDown(ByVal g As Graphics, ByVal aPos As PointF) Implements ICommand.RButtonDown
        If m_Step = 2 Then
            '清除圆心到起点的橡皮线
            Dim tempLine1 As New CLine(m_Center, m_Begin)
            tempLine1.Draw(g, CGElement.geDrawMode.Drag)
            tempLine1 = Nothing
            '清除圆心到终点的橡皮线
            Dim tempLine2 As New CLine(m_Center, m_End)
            tempLine2.Draw(g, CGElement.geDrawMode.Drag)
            tempLine2 = Nothing
            '清除橡皮弧
            Dim tempArc As New CArc(m_Center, m_Begin, m_End)
            tempArc.Draw(g, CGElement.geDrawMode.Drag)
            tempArc = Nothing
        End If
        m_Step = 0
    End Sub