locked
How to move the lineshape control at runtime freeely with mouse pointer

    Question

  • Hi PowerPacks ,

    The problem is I am drawing a LineShape control from Microsoft PowerPacks controls .dll , I am also moving the line when MouseDown,MouseMove,MouseUp, 

    But i am not able to drag the line in the correct position like in VB.net 2005

    MouseDown 
    fdragging =true 
    startx =0 
    starty =0 


    MouseMove 
    m_control.StartPoint = New Point((m_control.StartPoint.X + e.X) - startx, (m_control.StartPoint.Y + e.Y) - starty)
    m_control.EndPoint = New Point((m_control.EndPoint.X + e.X - startx), (m_control.EndPoint.Y + e.Y - starty))

    MouseUp 
    fdragging = false

    1) the things are i am not able to handle the MouseUp event also 

    2) the pointer is slipping from the line & not able move the line in the correct direction.

    I am not able to move th lineshape control freely like in the design environment . 

    And i am gettting the traces on the panel while moving the LineShape Control which looks odd to the end user .



    VS
    Friday, February 19, 2010 7:28 AM

Answers

All replies

  • Hi SilverPlate,

    If you want to move lineshape, you can change both the StartPoint and EndPoint of the control. Hope this helps.

        Private fdragging As Boolean = False
        Private startx As Integer = 0
        Private starty As Integer = 0
        Private startPointRec As Point
        Private endPointRec As Point
    
        Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
            fdragging = True
            startx = e.X
            starty = e.Y
            startPointRec = m_control.StartPoint
            endPointRec = m_control.EndPoint
        End Sub
    
        Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
            Dim movex As Integer = 0
            Dim movey As Integer = 0
            If fdragging Then
                movex = e.X - startx
                movey = e.Y - starty
                m_control.StartPoint = New Point(startPointRec.X + movex, startPointRec.Y + movey)
                m_control.EndPoint = New Point(endPointRec.X + movex, endPointRec.Y + movey)
            End If
        End Sub
    
        Private Sub Form1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
            fdragging = False
        End Sub
    If i misunderstand you, please let me know.

    Regards
    Jeff Shan
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Marked as answer by Jeff Shan Friday, February 26, 2010 2:00 AM
    • Unmarked as answer by SilverPlate Friday, February 26, 2010 10:31 AM
    Tuesday, February 23, 2010 9:26 AM
  • Hi Jeff Shan ,

    Thanks 4 replying ,its good but not for my requirement. 

    My requirement is i have to drag n drop by mousedown on Lineshape control . Here is the code i used.
     Dim fdragging, fMousedown As Boolean
        Dim StartX, startY As Integer
    
        Private Sub LineShape1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LineShape1.MouseDown
            fdragging = True
            StartX = e.X
            startY = e.Y
        End Sub
    
        Private Sub LineShape1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LineShape1.MouseMove
            Cursor.Current = Cursors.SizeAll
            If fdragging Then
                LineShape1.StartPoint = New Point(LineShape1.StartPoint.X + e.X - StartX, LineShape1.StartPoint.Y + e.Y - startY)
                LineShape1.EndPoint = New Point(LineShape1.EndPoint.X + e.X - StartX, LineShape1.EndPoint.Y + e.Y - startY)
            End If
        End Sub
    
        Private Sub LineShape1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ShapeContainer1.MouseUp
            fdragging = False
            StartX = 0
            startY = 0
        End Sub
    Regards,

    VS
    Friday, February 26, 2010 10:26 AM
  • Hello SilverPlate,

    You probably do not want to handle events on the LineShape as it has limited region. Probably Jeff's version is good and you may want to hit test on mouse down to see if the line is selected.

    John
    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    Sunday, February 28, 2010 8:56 PM
    Moderator
  • OK, it looks like this is a question follows up this thread:
    http://social.msdn.microsoft.com/Forums/en-US/vbpowerpacks/thread/5c29b36a-a74b-4477-903c-90af7a43a8eb

    Let's try to understand better your issue: 

    RE:  the things are i am not able to handle the MouseUp event also 
    If you are trying to use LineShape to handle the mouse up, you will stuck. You should use its parent container control to handle it. 

    RE:  the pointer is slipping from the line & not able move the line in the correct direction.

    If you use the LineShape to handle the mouse move event, etc. You will see the behavior like the cursor is "slipping".

    So the solution is you have to give up using the Mouse event on LineShape. Use ShapeContainer or Form's Mouse events. 

    I will post a sample later tonight. 

    John  

    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    Monday, March 01, 2010 3:53 AM
    Moderator
  • This sample (in form1 you have a LineShape1) works fine to me.


    Public Class Form1
        Const HitTestDelta As Integer = 3

        ' The mouse position when mouse down
        Dim oldMouseX As Integer
        Dim oldMouseY As Integer

        ' The line position when mouse down.
        Dim oldStartPoint As Point
        Dim oldEndPoint As Point

        Dim dragStartPoint As Boolean = False
        Dim dragEndPoint As Boolean = False

        Private Sub ShapeContainer1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ShapeContainer1.MouseDown
            If (LineShape1.HitTest(MousePosition.X, MousePosition.Y)) Then
                oldMouseX = e.X
                oldMouseY = e.Y
                oldStartPoint = LineShape1.StartPoint
                oldEndPoint = LineShape1.EndPoint

                dragStartPoint = MouseIsNearBy(oldStartPoint)
                dragEndPoint = MouseIsNearBy(oldEndPoint)
                If (Not dragStartPoint AndAlso Not dragEndPoint) Then
                    'If not drag either end, then drag both.
                    dragStartPoint = True
                    dragEndPoint = True
                End If
            End If
        End Sub

        Private Sub ShapeContainer1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ShapeContainer1.MouseMove
            If (dragStartPoint) Then
                LineShape1.StartPoint = New Point(oldStartPoint.X + e.X - oldMouseX, oldStartPoint.Y + e.Y - oldMouseY)
            End If
            If (dragEndPoint) Then
                LineShape1.EndPoint = New Point(oldEndPoint.X + e.X - oldMouseX, oldEndPoint.Y + e.Y - oldMouseY)
            End If
        End Sub

        Private Sub ShapeContainer1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ShapeContainer1.MouseUp
            dragStartPoint = False
            dragEndPoint = False
        End Sub

        Private Function MouseIsNearBy(ByVal testPoint As Point) As Boolean
            testPoint = Me.PointToScreen(testPoint)
            Return Math.Abs(testPoint.X - MousePosition.X) <= HitTestDelta AndAlso Math.Abs(testPoint.Y - MousePosition.Y) <= HitTestDelta
        End Function

    End Class

    Hope this help.


    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    • Marked as answer by SilverPlate Tuesday, March 02, 2010 7:14 AM
    • Unmarked as answer by SilverPlate Tuesday, March 02, 2010 10:04 AM
    Monday, March 01, 2010 4:07 AM
    Moderator
  • Hi John ,

    Thanks its working .This is the thing i need 4 drag n drop Thank u very much .

    set Form1.BackColor = white

    But i have one more problem with LineShape while resizing the endpoints or drag n drop

    1)   Just take the end point or start point then rotate in a circular fashion then trailing or some paint things left on the screen .



    How can we smoothly drag n drop the line like in vs designer without any traces or ?


    I m also having problem with controls also

    http://cid-038dd0e1974d763e.skydrive.live.com/self.aspx/Images/Trailing%20Effect%203%20Controls%20Handlers%20Appearing.JPG



    Regards
    VS
    • Edited by SilverPlate Tuesday, March 02, 2010 10:10 AM Trailing of control
    Tuesday, March 02, 2010 7:16 AM
  • Hi SilverPlate, 

    What is the issue of "Just take the end point or start point then rotate in a circular fashion then trailing or some paint things left on the screen"? Could you please paste a picture as well.
    I do know an issue when the line width is large enough and the drag will have some tailing. If you have the picture, I can confirm that.

    For the controls, I think we need a separate thread to start with. We will need to see how you do the drag and drop on controls.


    John


    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    Wednesday, March 03, 2010 7:18 AM
    Moderator
  • Hi All,

    Just post a blog based on this topic:

    http://blogs.msdn.com/vsdata/archive/2010/03/02/how-to-move-a-shape-control-with-mouse-events.aspx

    Hope this is helpful.
    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    Wednesday, March 03, 2010 8:11 AM
    Moderator
  • Great work John, i'm really impressed by your work.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Wednesday, March 03, 2010 8:44 AM
  • Thank you Jeff, I am glad I can be helpful and let me know if you have any ideas that we can blog about.
    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    Wednesday, March 03, 2010 4:59 PM
    Moderator
  • Hi John ,

    Thank you for the solution . i set in my appl according to my requirement.

    I am not able upload the image bcoz sites are blocked . So i can reproduce by using some points

    X1= 125
    Y1 = 111

    X2= 371
    Y2 = 64


    1) Hold X2,Y2 then move towards  or reaching to x1,y1 by decreasing the distance b/w two points then paint marks or trailing are distributed across the form .

    2)  X1= 125 ,X2=128 ,y1=126 ,y2=126 rotate in a fashion that x1,y1 has to come down by increasing the distance b.w the 2 points  then also paint marks or trailing are shown

    3) X1=695 ,X2 =158,Y1=49,Y2=46

    sample  Form1

    Hold the lineshape ctrl at left ,right ,center or  at any place then drag to down to form's bottom position then u see the trailing of paint marks or lIneshape control ... This is what i am telling . How to get rid off this one .



    Regards,


    VS
    • Edited by SilverPlate Thursday, March 04, 2010 9:13 AM Trailing
    Thursday, March 04, 2010 7:28 AM
  • Hi SilverPlate,

    Could you please post a picture to any site that I can see or send it to me through johnchenms@live.com, where I only used to receive files.

    I had a hard time to uderstand your issue without a picture.

    Thanks!
    John
    John Chen -- See my team blog: http://blogs.msdn.com/vsdata. All my posts are provided "AS IS" with no warranties, and confer no rights.
    Sunday, March 07, 2010 7:35 AM
    Moderator
  • Hi John,

    thank you very much for your work. After days of working and searching I was so glad to find your solution :-)

    I have added some lines to your code. Now it is possible to generate new LineShapes on runtime, just clicking the button.

    You can also open a ContextMenuStrip with right mouse click on a line shape. For setting of color and line width.

    But I have three problems that I still can not solve.

    1) When I drag a LineShape over the blue colored PictureBox it leaves traces on it. Also on the button.

    2) Dragging one ShapeLine over the other erases it like with a rubber.

    3) extending a LineShape over the whole screen, picking the endpoint and dragging it fast around leaves traces on the form.

    I have added a refresh to the mouse up handler, but that is not really satisfying.

    If you have some extensions or remarks I would like to hear them.

    Here is the code for Form1 (add a Button):

    Imports Microsoft.VisualBasic.PowerPacks
    
    
    Public Class Form1
    
      Private PictureBox1 As New PictureBox
    
      Private mLineShapes() As LineShape = Nothing
      Private mShapeContainer() As ShapeContainer = Nothing
    
      Private WithEvents mLsCtm1 As New ContextMenuStrip
      Private WithEvents mLsItm1 As New ToolStripMenuItem
      Private WithEvents mLsItm2 As New ToolStripMenuItem
    
      ' declare the ContextMenuStrip control
      Private mLsRtbContextMenuStrip As New ContextMenuStrip
    
      Private Sub Form1_Load _
      (ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
        ' make some settings for ContextMenuStrip and its items
        mLsCtm1.Items.AddRange(New ToolStripItem() {mLsItm1, mLsItm2})
        mLsCtm1.Name = "ContextMenuStrip1"
        mLsCtm1.Size = New Size(142, 56)
    
        mLsItm1.Name = "Item1ToolStripMenuItem"
        mLsItm1.Size = New System.Drawing.Size(141, 26)
        mLsItm1.Text = "Linienfarbe"
    
        mLsItm2.Name = "Item2ToolStripMenuItem"
        mLsItm2.Size = New System.Drawing.Size(141, 26)
        mLsItm2.Text = "Linienstärke"
    
        PictureBox1.Height = 300
        PictureBox1.Width = 500
        PictureBox1.Location = New Point(300, 100)
        PictureBox1.BackColor = Color.Blue
        Me.Controls.Add(PictureBox1)
    
      End Sub
    
      Private Sub mLsItm1_Click _
      (ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _
      mLsItm1.Click
    
        Dim colorPicker As New ColorDialog()
    
        Try
          colorPicker.ShowHelp = True
    
          Dim ClickedShapeContainerName As String = mLsCtm1.SourceControl.Name
          Dim siI As Integer
          Dim siClickedShapeContainerId As Integer = -1
    
          ' get ID of clicked ShapeContainer
          For siI = 0 To mShapeContainer.Length
            If mShapeContainer(siI).Name = ClickedShapeContainerName Then
              siClickedShapeContainerId = siI
              Exit For
            End If
          Next
    
          ' get connected LineShape with same ID
          colorPicker.Color = mLineShapes(siClickedShapeContainerId).BorderColor
    
    
          If (colorPicker.ShowDialog() = Windows.Forms.DialogResult.OK) Then
            mLineShapes(siClickedShapeContainerId).BorderColor = colorPicker.Color
          End If
    
        Catch ex As Exception
          MessageBox.Show("Sub ITM1_Click: " & ex.Message, Me.Text)
        End Try
    
        colorPicker.Dispose()
      End Sub
    
      Private Sub mLsItm2_Click _
      (ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _
      mLsItm2.Click
    
        Dim myDlgLineWidth As New DlgLineWidth
    
        Try
    
          Dim ClickedShapeContainerName As String = mLsCtm1.SourceControl.Name
          Dim siI As Integer
          Dim siClickedShapeContainerId As Integer = -1
    
          ' get ID of clicked ShapeContainer
          For siI = 0 To mShapeContainer.Length
            If mShapeContainer(siI).Name = ClickedShapeContainerName Then
              siClickedShapeContainerId = siI
              Exit For
            End If
          Next
    
          ' get connected LineShape with same ID
          myDlgLineWidth.LineWidth = mLineShapes(siClickedShapeContainerId).BorderWidth
    
          If myDlgLineWidth.ShowDialog = Windows.Forms.DialogResult.OK Then
            mLineShapes(siClickedShapeContainerId).BorderWidth = myDlgLineWidth.LineWidth
          End If
    
        Catch ex As Exception
          MessageBox.Show("Sub ITM2_Click: " & ex.Message, Me.Text)
        End Try
    
        myDlgLineWidth.Dispose()
    
      End Sub
    
      Private Sub Button1_Click _
      (ByVal sender As System.Object, ByVal e As System.EventArgs) _
      Handles Button1.Click
    
        ' declare ShapeContainer counter
        Dim siSCCount As Integer
        If IsNothing(mLineShapes) Then
          siSCCount = 0
        Else
          siSCCount = mLineShapes.Length
        End If
    
        ' 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 = 8
    
        ' 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
    
        ' add handlers
        AddHandler mShapeContainer(siSCCount).MouseDown, _
        AddressOf ShapeContainerMouseDownEventHandler
    
        AddHandler mShapeContainer(siSCCount).MouseMove, _
        AddressOf ShapeContainerMouseMoveEventHandler
    
        AddHandler mShapeContainer(siSCCount).MouseUp, _
        AddressOf ShapeContainerMouseUpEventHandler
      End Sub
    
    
      Const HitTestDelta As Integer = 3
    
      ' The mouse position when mouse down 
      Dim oldMouseX As Integer
      Dim oldMouseY As Integer
    
      ' The line position when mouse down. 
      Dim oldStartPoint As Point
      Dim oldEndPoint As Point
    
      Dim dragStartPoint As Boolean = False
      Dim dragEndPoint As Boolean = False
    
      Private Sub ShapeContainerMouseDownEventHandler _
      (ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
        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)
    
          myShapeContainer.BringToFront()
    
          If (myLineShape.HitTest(MousePosition.X, MousePosition.Y)) Then
            oldMouseX = e.X
            oldMouseY = e.Y
            oldStartPoint = myLineShape.StartPoint
            oldEndPoint = myLineShape.EndPoint
    
            dragStartPoint = MouseIsNearBy(oldStartPoint)
            dragEndPoint = MouseIsNearBy(oldEndPoint)
            If (Not dragStartPoint AndAlso Not dragEndPoint) Then
              'If not drag either end, then drag both. 
              dragStartPoint = True
              dragEndPoint = True
            End If
            myLineShape.SelectionColor = Color.Transparent
          End If
        End If
    
    
      End Sub
    
      Private Sub ShapeContainerMouseMoveEventHandler _
      (ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
        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 (dragStartPoint) Then
            myLineShape.StartPoint = New Point(oldStartPoint.X + e.X - oldMouseX, oldStartPoint.Y + e.Y - oldMouseY)
          End If
          If (dragEndPoint) Then
            myLineShape.EndPoint = New Point(oldEndPoint.X + e.X - oldMouseX, oldEndPoint.Y + e.Y - oldMouseY)
          End If
    
          ' try something ...
          ' clean everything from trace marks
          'myLineShape.Invalidate()
          'myShapeContainer.Parent.Refresh()
    
          'Me.Invalidate()
          'For siI As Integer = 0 To Me.Controls.Count - 1
          '  Me.Controls.Item(siI).Invalidate()
          'Next
    
        End If
    
      End Sub
    
      Private Sub ShapeContainerMouseUpEventHandler _
      (ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
        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)
    
          dragStartPoint = False
          dragEndPoint = False
          myLineShape.SelectionColor = Color.Transparent
        End If
    
        myShapeContainer.Parent.Refresh()
    
        ' try something ...
        'Me.Invalidate()
        'For siI As Integer = 0 To Me.Controls.Count - 1
        '  Me.Controls.Item(siI).Invalidate()
        'Next
    
      End Sub
    
      Private Function MouseIsNearBy(ByVal testPoint As Point) As Boolean
        testPoint = Me.PointToScreen(testPoint)
        Return Math.Abs(testPoint.X - MousePosition.X) <= HitTestDelta _
        AndAlso Math.Abs(testPoint.Y - MousePosition.Y) <= HitTestDelta
      End Function
    
    End Class
    

    And this is the code for sub dialog (add TextBox1 and Button1):

    Public Class DlgLineWidth
    
      Private mLineWidth As Integer
    
      Public Property LineWidth() As Integer
        Get
          Return mLineWidth
        End Get
        Set(ByVal value As Integer)
          mLineWidth = value
        End Set
      End Property
    
      ' button "ok"
      Private Sub Button1_Click _
      (ByVal sender As System.Object, ByVal e As System.EventArgs) _
      Handles Button1.Click
    
        Try
          mLineWidth = CInt(TextBox1.Text)
        Catch ex As Exception
          MessageBox.Show("Please enter an integer." & ex.Message, Me.Text)
        End Try
    
      End Sub
    
      Private Sub DlgLineWidth_Load _
      (ByVal sender As System.Object, ByVal e As System.EventArgs) _
      Handles MyBase.Load
    
        TextBox1.Text = mLineWidth
    
      End Sub
    End Class

    Greetings,

       Mike

    Friday, April 23, 2010 6:55 PM