交互技术及其实现

常见的交互绘图技术包括用鼠标绘图、橡皮线绘制、拾取、选择、变换、相交线、定位和界面交互等。下面主要介绍最基础的鼠标绘图和橡皮线绘"制技术,后面各章节还要陆续讲到拾取、选择、变换、相交线和界面交互。

用鼠标绘图

在电脑屏幕上,鼠标的光标就像我们的画笔,通过单击和移动鼠标可以实现交互绘图。用鼠标绘图时,要触发一系列鼠标事件。如按下鼠标键时触发MouseDown事件,移动鼠标时触发MouseMove事件.NET中部分鼠标事件及说明表2-1所示。

表2-1鼠标事件及说明

Document Image
\[\]

下面的程序在窗体上画一个方框,鼠标在方框内外移动,或者在方框内单击时显示相应的说明文字到方框下面的文本框中。

code.vb.net
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    Dim g As Graphics = e.Graphics
    Dim pen As New Pen(Color.Blue, 3)
    g.DrawRectangle(pen, 100, 20, 200, 200)
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
    TextBox1.Text = " "
    If InBox(e.X, e.Y) Then
        TextBox1.Text = "当前鼠标在方框内移动。"
    Else
        TextBox1.Text = "当前鼠标在方框外移动。"
    End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
    If InBox(e.X, e.Y) Then
        TextBox1.Text = " "
        If e.Button = MouseButtons.Left Then
            TextBox1.Text = "当前鼠标左键在方框内按下。"
        ElseIf e.Button = MouseButtons.Right Then
            TextBox1.Text = "当前鼠标右键在方框内按下。"
        End If
    End If
End Sub
Private Function InBox(ByVal x As Single, ByVal y As Single) As Boolean
    If x > 100 And x < 300 And y > 20 And y < 220 Then
        Return True
    Else
        Return False
    End If
End Function

程序运行结果如图2-3所示。

Document Image
\[\]

图2-3 鼠标事件测试

橡皮线

橡皮线技术是交互绘图过程中必不可少的一种技术,它试图实现一种类似于橡皮线的绘图效果。橡皮线的一端固定以后,牵引另一端,可以随意地改变方向和长短,直到它也固定在某个点上。使用这种技术以后,就可以以一种直观的形式描述绘制直线段中定位起点和终点之间的过程。

在计算机上实现橡皮线效果采用了一些"障眼法"。实际上,在线条动态绘制的过程中,屏幕上在不断地擦除原来位置上的图元显示,然后在新位置上绘制图元。此过程中,直线段的起点不变,而终点不断变化。由于计算机的绘制速度很快,肉眼几乎觉察不出擦除图元和显示新图元的过程。

与橡皮线类似的还有橡皮矩形、橡皮圆和橡皮弧等。它们的工作机理与橡皮线大同小异。下面的程序演示了橡皮矩形的实现过程。第1次单击鼠标左键时,确定矩形的第1个顶点。在移动鼠标光标的过程中,鼠标光标的当前位置作为第2个顶点,以橡皮矩形的形式显示矩形。第2次单击鼠标左键时,确定矩形中第1个顶点的对角顶点,绘制矩形。下面的程序中用到了API函数SetROP2和Rectangle,分别设置绘图模式和绘制矩形。

code.vb.net
    <DllImport("gdi32.dll")> _
     Private Shared Function SetROP2(ByVal hdc As IntPtr, _
         ByVal nDrawMode As Integer) As Boolean
    End Function
    <DllImport("gdi32.dll")> _
    Private Shared Function Rectangle _
        (ByVal hdc As IntPtr, ByVal X1 As Integer, ByVal Y1 As Integer, _
        ByVal X2 As Integer, ByVal Y2 As Integer) As Boolean
    End Function
    Private m_StartX, m_StartY As Single
    Private m_EndX, m_EndY As Single
    Private m_Step As Integer = 0
    Protected Overrides Sub OnMouseDown(ByVal e As Windows.Forms.MouseEventArgs)
        Dim g As Graphics = Me.CreateGraphics()
        Dim hdc As IntPtr = g.GetHdc()
        m_Step += 1
        SetROP2(hdc, 10)
        If m_Step = 1 Then
            m_StartX = e.X
            m_StartY = e.Y
            m_EndX = e.X
            m_EndY = e.Y
        ElseIf m_Step = 2 Then
            Rectangle(hdc, m_StartX, m_StartY, m_EndX, m_EndY)
            Rectangle(hdc, m_StartX, m_StartY, e.X, e.Y)
            m_Step = 0
        End If
        g.ReleaseHdc(hdc)
    End Sub
    Protected Overrides Sub OnMouseMove(ByVal e As Windows.Forms.MouseEventArgs)
        Dim g As Graphics = Me.CreateGraphics()
        Dim prex As Single, prey As Single
        If m_Step = 1 Then
            Dim hdc As IntPtr = g.GetHdc()
            prex = m_EndX
            prey = m_EndY
            SetROP2(hdc, 10)
            Rectangle(hdc, m_StartX, m_StartY, prex, prey)
            Rectangle(hdc, m_StartX, m_StartY, e.X, e.Y)
            m_EndX = e.X
            m_EndY = e.Y
            g.ReleaseHdc(hdc)
        End If
    End Sub
    Protected Overrides Sub OnPaint(ByVal e As Windows.Forms.PaintEventArgs)
        Dim g As Graphics = e.Graphics
        g.FillRectangle(Brushes.White, Me.ClientRectangle)
    End Sub

程序运行结果如图2-4所示。

Document Image
\[\]

图2-4实现橡皮矩形