2

以下のコードを使用して、複数の LineShape コントロールを Windows フォームに追加しています。作成された新しい LineShape オブジェクトを格納する 、グローバルに宣言さmLineShapes()れた配列 (コードの下部) に注意してください。mShapeContainter()

現在、特定の 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 

したがって、mLineShapes() 配列と mShapeControl() 配列を使用せずに新しい LineShape をフォーム コントロールに追加するだけの場合、上記のコード (ストレージ配列で LineShape を見つける) を変更して、行を変更できるようにするにはどうすればよいでしょうか? LineShape をクリックすると、.sourcecontrol または .parent を使用してその名前を取得できると思いますか?

2019 年 5 月 9 日更新

Form1 のコントロールを右クリックし、ContextMenuStrip から「リンク」コマンドを選択すると、次のメソッド (ctmsconnect) が起動されて新しい LineShape コントロールが描画され、ユーザーはそれをワークフローの次のコントロールにドラッグ アンド ドロップします。質問は、LineShapes (「Lines」) のリストは不要ですか?

(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 に答える