Удалить LineShape из массивов Windows Form, LineShape и ShapeContainer


Я использую приведенный ниже код для добавления нескольких элементов управления LineShape в форму Windows. Обратите внимание на глобально объявленные массивы mLineShapes() и mShapeContainter() (в нижней части кода), которые хранят каждый новый объект LineShape после его создания.

В настоящее время мне не удалось удалить данный элемент управления LineShape из формы (даже если я знаю его индекс массива), а также не удается удалить элемент массива, не вызвав ничего для удаленного элемента. Очевидно, как только я удалю элемент из этих массивы, он требует, чтобы все остальные элементы с большими индексами копировались в меньшие значения, чтобы заполнить ничем не опустошенный элемент. Учитывая эти обстоятельства, можно ли использовать списки вместо массивов 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

В дополнение к вышесказанному, конечные точки каждого Линейные формы выбираются из массивов таким образом, чтобы их можно было перемещать. Пример приведен ниже:

        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 

Поэтому, если я просто добавлю новую линейную форму к элементам управления формы без использования mLineShapes () ans массивы mShapeControl (), как я могу изменить приведенный выше код (который находит форму строки в массивах хранения), чтобы можно было изменить строку? Я думаю, что если я нажму на Линешейп ,я могу получить его имя с помощью.sourcecontrol или .родитель?

2 2

2 ответа:

Вам не нужны массивы, просто используйте коллекцию элементов управления. Вместо установки родительского элемента управления, вероятно, следует добавить его в коллекцию:

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

Чтобы удалить их, вы можете ссылаться на них по свойству name:

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

Элементы управления shape внутри 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 для каждой формы или контейнера; это может привести к неожиданному поведению. Если вы добавляете строку времени разработки или элемент управления shape в форму или контейнер после написания кода для его создания программным способом, вы должны изменить этот код, чтобы использовать ShapeContainer, созданный дизайнером.

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