2

我正在使用下面的代码将多个 LineShape 控件添加到 Windows 窗体。请注意全局声明mLineShapes()mShapeContainter()数组(在代码底部),它们在创建每个新 LineShape 对象后存储它。

目前,我无法从表单中删除给定的 LineShape 控件(即使我知道它的数组索引),并且也无法删除数组元素而不导致已删除元素的 Nothing。显然,一旦我从这些数组中删除了元素,就需要将所有具有更大索引的剩余元素复制到更低的值以填充 Nothing voided 元素。鉴于这些情况,可以使用列表来代替mLineShapes()mShapeContainer()数组吗?

        enter code here' create new ShapeContainer
        Dim sSCTemp As New ShapeContainer

        ' add ShapeContainer to Form
        sSCTemp.Parent = Me

        ' create new LineShape
        Dim sLSTemp As New LineShape
        sLSTemp.BorderColor = Color.Black
        sLSTemp.BorderWidth = 2
        sLSTemp.Cursor = Cursors.Cross
        ' add LineShape to ShapeContainer
        sLSTemp.Parent = sSCTemp

        ' set starting and ending coordinates for the line
        sLSTemp.StartPoint = New System.Drawing.Point(siSCCount * 20, 60 + siSCCount * 60)
        sLSTemp.EndPoint = New System.Drawing.Point(100 + siSCCount * 20, 110 + siSCCount * 60)

        ' set new LineShape to top of z-order
        sLSTemp.BringToFront()
        sSCTemp.BringToFront()

        ' connect ContextMenuStrip to LineShape
        sLSTemp.ContextMenuStrip = mLsCtm1

        ' add new LineShape to arrays
        ReDim Preserve mLineShapes(siSCCount)
        ReDim Preserve mShapeContainer(siSCCount)

        mLineShapes(siSCCount) = sLSTemp
        mLineShapes(siSCCount).Name = "LineShape" & siSCCount
        mShapeContainer(siSCCount) = sSCTemp
        mShapeContainer(siSCCount).Name = "ShapeContainer" & siSCCount

除了上述之外,每个 LineShape 的端点都是从数组中选择的,以便它们可以移动。下面是一个例子:

        Dim siSCId As Integer
        Dim myShapeContainer As ShapeContainer
        myShapeContainer = CType(sender, ShapeContainer)
        Dim myLineShape As LineShape
        ' get index of the actual ShapeContainer in ShapeContainer array
        siSCId = Array.IndexOf(mShapeContainer, sender)

        If siSCId > -1 Then
            myLineShape = mLineShapes(siSCId)
            If MouseIsNearBy(myLineShape.EndPoint) Then
                myLineShape.BorderColor = Color.Red
                NearLineEndPoint = True
            End If
            If MouseIsNearBy(myLineShape.EndPoint) = False Then
                myLineShape.BorderColor = Color.Black
                NearLineEndPoint = False
            End If
            If (dragStartPoint) Then
                myLineShape.StartPoint = New Point(oldStartPoint.X + e.X - oldMouseX, oldStartPoint.Y + e.Y - oldMouseY)
            End If
        End If 

因此,如果我只是简单地将新的 LineShape 添加到表单控件而不使用 mLineShapes() 和 mShapeControl() 数组,我该如何修改上面的代码(在存储数组中找到 LineShape)以便可以修改线?我认为如果我单击 LineShape,我可以使用 .sourcecontrol 或 .parent 来获取它的名称?

2019 年 5 月 9 日更新

右键单击 Form1 上的控件并从 ContextMenuStrip 中选择“链接”命令后,将触发以下方法 (ctmsconnect) 以绘制新的 LineShape 控件,然后用户将其拖放到工作流中的下一个控件上。问题是,不需要 LineShapes(“线条”)列表吗?

(在 Form1 类声明中):

  Dim SC As New ShapeContainer
  Dim Lines As New List(Of LineShape)

  Private Sub ctmsconnect_Click(sender As System.Object, e As System.EventArgs) Handles ctmsconnect.Click
        mLineWidth = 1
        Dim myItem As ToolStripMenuItem = CType(sender, ToolStripMenuItem)
        Dim cms As ContextMenuStrip = CType(myItem.Owner, ContextMenuStrip)
        Dim x As Integer = cms.SourceControl.Right - 2
        Dim y As Integer = cms.SourceControl.Top + (cms.SourceControl.Height / 2 - 12)
        Dim LS As New LineShape
        NumLineShapes += 1
        LS.Name = "LineShape" & NumLineShapes
        LS.BorderColor = Color.Black
        LS.BorderWidth = 2

        'Set starting and ending coordinates for the line
        LS.StartPoint = New Point(x, y)
        LS.EndPoint = New Point(x + 80, y - 5)

        'Set new LineShape to top of z-order
        LS.BringToFront()

        Dim nxgContextMenuStrip As New ContextMenuStrip
        LS.ContextMenuStrip = nxgContextMenuStrip
        LS.Tag = "LineShape" & NumLineShapes & "_Delete"

        'Attach an event handler for the ContextMenuStrip control's Opening event. 
        AddHandler nxgContextMenuStrip.Opening, AddressOf cms_Opening
        numconnectedlineendpoints += 1
        Dim myValues As New List(Of String)
        myValues.Add(cms.SourceControl.Name)
        DropLineOriginalObjectName = cms.SourceControl.Name
        OrigDropControl = cms.SourceControl
        myValues.Add(LS.Name)
        myValues.Add("linestart")
        dicGUIControls.Add(numconnectedlineendpoints, myValues)
        Lines.Add(LS)
        SC.Shapes.Add(LS)
        Me.Refresh()

    End Sub
4

2 回答 2

2

您不需要数组,只需使用控件集合。您应该将它们添加到集合中,而不是设置控件的父级:

'sSCTemp.Parent = Me
Me.Controls.Add(sSCTemp)

要删除它们,您可以通过 name 属性引用它们:

If Me.Controls.ContainsKey("ShapeContainer1") Then
  Me.Controls.RemoveByKey("ShapeContainer1")
End If

ShapeContainer 内的形状控件必须通过 Shape 集合访问:

If Me.Controls.ContainsKey("ShapeContainer1") Then
  Dim sc As ShapeContainer = DirectCast(Me.Controls("ShapeContainer1"), ShapeContainer)
  If sc.Shapes.ContainsKey("LineShape2") Then
    sc.Shapes.RemoveAt(sc.Shapes.IndexOfKey("LineShape2"))
  End If
End If

读取 StartPoint 和 EndPoint 属性的示例:

Dim sb As New StringBuilder
For Each ls As LineShape In Me.ShapeContainer1.Shapes
  sb.AppendLine(ls.StartPoint.ToString & " - " & ls.EndPoint.ToString)
Next
MessageBox.Show(sb.ToString)

注意:ShapeContainer 类特别注意:

注意不要为每个表单或容器创建多个 ShapeContainer;这样做可能会引入意外行为。如果您在编写代码以编程方式创建后将设计时线条或形状控件添加到窗体或容器,则应修改该代码以使用设计器创建的 ShapeContainer。

于 2013-01-02T14:50:57.907 回答
0
Public Class Form1

    Dim canvas As New Microsoft.VisualBasic.PowerPacks.ShapeContainer
    ' Set the form as the parent of the ShapeContainer.

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        canvas.Parent = Me
        ' Set the ShapeContainer as the parent of the LineShape.
    End Sub

    Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
        If RadioButton1.Checked = True Then
            Dim line1 As New Microsoft.VisualBasic.PowerPacks.LineShape
            line1.Parent = canvas
            ' Set the starting and ending coordinates for the line.
            line1.StartPoint = New System.Drawing.Point(Me.Width / 2, 0)
            line1.EndPoint = New System.Drawing.Point(e.X, e.Y)
            TextBox1.Text = canvas.Shapes.Count.ToString
            line1.Name = "MyShape"
            canvas.Shapes.Add(line1)
            AddHandler line1.Click, AddressOf LineClick
        End If
    End Sub

    Private Sub LineClick(sender As Object, e As EventArgs)
        ' Here is where we take the object that is sender from the arguments and cast it to its specific control
        If RadioButton2.Checked = True Then
            ' I could just as easily use
            CType(sender, PowerPacks.LineShape).Dispose()
            TextBox1.Text = canvas.Shapes.Count
        End If
    End Sub

End Class
于 2014-10-24T17:53:11.617 回答