Click here to Skip to main content
15,896,606 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
VB
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
       If e.KeyCode = Keys.Down Then
          movelineup()
       ElseIf e.KeyCode = Keys.Up Then
           movelinedown()
       End If
   End Sub

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Me.KeyPreview = True
   End Sub


What I have tried:

now what should i Right in the function so it can work with a multi line text box

Code borrowed but can't get to work:
VB
'' Duplicates the current line (or selection of lines) and places the copy
'' one line below or above the current cursor position (based upon the parameter)
Sub CopyLine(ByVal movingDown As Boolean)
    DTE.UndoContext.Open("CopyLine")
    Dim objSel As TextSelection = DTE.ActiveDocument.Selection

    ' store the original selection and cursor position
    Dim topPoint As TextPoint = objSel.TopPoint
    Dim bottomPoint As TextPoint = objSel.BottomPoint
    Dim lTopLine As Long = topPoint.Line
    Dim lTopColumn As Long = topPoint.LineCharOffset
    Dim lBottomLine As Long = bottomPoint.Line
    Dim lBottomColumn As Long = bottomPoint.LineCharOffset()

    ' copy each line from the top line to the bottom line
    Dim readLine As Long = lTopLine
    Dim endLine As Long = lBottomLine + 1
    Dim selectionPresent As Boolean = ((lTopLine <> lBottomLine) Or (lTopColumn <> lBottomColumn))
    If (selectionPresent And (lBottomColumn = 1)) Then
        ' A selection is present, but the cursor is in front of the first character
        ' on the bottom line. exclude that bottom line from the copy selection.
        endLine = lBottomLine
    End If

    ' figure out how many lines we are copying, so we can re-position
    ' our selection after the copy is done
    Dim verticalOffset As Integer = 0
    If (movingDown) Then
        verticalOffset = endLine - lTopLine
    End If

    ' copy each line, one at a time.
    ' The Insert command doesn't handle multiple lines well, and we need
    ' to use Insert to avoid autocompletions
    Dim insertLine As Long = endLine
    While (readLine < endLine)
        ' move to read postion, and read the current line
        objSel.MoveToLineAndOffset(readLine, 1)
        objSel.EndOfLine(True) 'extend to EOL
        Dim lineTxt As String = objSel.Text.Clone
        ' move to the destination position, and insert the copy
        objSel.MoveToLineAndOffset(insertLine, 1)
        objSel.Insert(lineTxt)
        objSel.NewLine()
        ' adjust the read & insertion points
        readLine = readLine + 1
        insertLine = insertLine + 1
    End While

    ' restore the cursor to original position and selection
    objSel.MoveToLineAndOffset(lBottomLine + verticalOffset, lBottomColumn)
    objSel.MoveToLineAndOffset(lTopLine + verticalOffset, lTopColumn, True)
    DTE.UndoContext.Close()
End Sub

'' Duplicates the current line (or selection of lines) and places the copy
'' one line below the current cursor position
Sub CopyLineDown()
    CopyLine(True)
End Sub

'' Duplicates the current line (or selection of lines) and places the copy
'' one line above the current cursor position
Sub CopyLineUp()
    CopyLine(False)
End Sub


'' Moves the selected lines up one line. If no line is
'' selected, the current line is moved.
''
Sub MoveLineUp()
    DTE.UndoContext.Open("MoveLineUp")
    Dim objSel As TextSelection = DTE.ActiveDocument.Selection
    ' store the original selection and cursor position
    Dim topPoint As TextPoint = objSel.TopPoint
    Dim bottomPoint As TextPoint = objSel.BottomPoint
    Dim lTopLine As Long = topPoint.Line
    Dim lTopColumn As Long = topPoint.LineCharOffset
    Dim lBottomLine As Long = bottomPoint.Line
    Dim lBottomColumn As Long = bottomPoint.LineCharOffset()

    Dim textLineAbove As TextSelection = DTE.ActiveDocument.Selection
    textLineAbove.MoveToLineAndOffset(lTopLine - 1, 1, False)
    textLineAbove.MoveToLineAndOffset(lTopLine, 1, True)
    Dim indentChange As Integer = CountIndentations(textLineAbove.Text) * -1

    ' If multiple lines are selected, but the bottom line doesn't
    ' have any characters selected, don't count it as selected
    Dim lEffectiveBottomLine = lBottomLine
    If ((lBottomColumn = 1) And (lBottomLine <> lTopLine)) Then
        lEffectiveBottomLine = lBottomLine - 1
    End If

    ' move to the line above the top line
    objSel.MoveToLineAndOffset(lTopLine - 1, 1)
    ' and move it down, until its below the bottom line:
    Do
        DTE.ExecuteCommand("Edit.LineTranspose")
    Loop Until (objSel.BottomPoint.Line >= lEffectiveBottomLine)
    ' Since the line we are on has moved up, our location in the file has changed:
    lTopLine = lTopLine - 1
    lBottomLine = lBottomLine - 1

    IndentBlockAndRestoreSelection(objSel, lBottomLine, lBottomColumn, lTopLine, lTopColumn, indentChange)

    DTE.UndoContext.Close()
End Sub

'' Moves the selected lines down one line. If no line is
'' selected, the current line is moved.
''
Sub MoveLineDown()
    DTE.UndoContext.Open("MoveLineDown")
    Dim objSel As TextSelection = DTE.ActiveDocument.Selection
    ' store the original selection and cursor position
    Dim topPoint As TextPoint = objSel.TopPoint
    Dim bottomPoint As TextPoint = objSel.BottomPoint
    Dim lTopLine As Long = topPoint.Line
    Dim lTopColumn As Long = topPoint.LineCharOffset
    Dim lBottomLine As Long = bottomPoint.Line
    Dim lBottomColumn As Long = bottomPoint.LineCharOffset()

    ' If multiple lines are selected, but the bottom line doesn't
    ' have any characters selected, don't count it as selected
    Dim lEffectiveBottomLine = lBottomLine
    If ((lBottomColumn = 1) And (lBottomLine <> lTopLine)) Then
        lEffectiveBottomLine = lBottomLine - 1
    End If

    Dim textLineBelow As TextSelection = DTE.ActiveDocument.Selection
    textLineBelow.MoveToLineAndOffset(lEffectiveBottomLine + 1, 1, False)
    textLineBelow.MoveToLineAndOffset(lEffectiveBottomLine + 2, 1, True)
    Dim indentChange As Integer = CountIndentations(textLineBelow.Text)


    ' move to the bottom line
    objSel.MoveToLineAndOffset(lEffectiveBottomLine, 1)
    ' and move it down, which effectively moves the line below it up
    ' then move the cursor up, always staying one line above the line
    ' that is moving up, and keep moving it up until its above the top line:
    Dim lineCount As Long = lEffectiveBottomLine - lTopLine
    Do
        DTE.ExecuteCommand("Edit.LineTranspose")
        objSel.LineUp(False, 2)
        lineCount = lineCount - 1
    Loop Until (lineCount < 0)
    ' Since the line we are on has moved down, our location in the file has changed:
    lTopLine = lTopLine + 1
    lBottomLine = lBottomLine + 1

    IndentBlockAndRestoreSelection(objSel, lBottomLine, lBottomColumn, lTopLine, lTopColumn, indentChange)

    DTE.UndoContext.Close()
End Sub

'' This method takes care of indenting the selected text by the indentChange parameter
'' It then restores the selection to the lTopLine:lTopColumn - lBottomLine:lBottomColumn parameter.
'' It will adjust these values according to the indentChange performed
Sub IndentBlockAndRestoreSelection(ByVal objSel As TextSelection, ByVal lBottomLine As Long, ByVal lBottomColumn As Long, ByVal lTopLine As Long, ByVal lTopColumn As Long, ByVal indentChange As Integer)
    ' restore the cursor to original position and selection
    objSel.MoveToLineAndOffset(lBottomLine, lBottomColumn)
    objSel.MoveToLineAndOffset(lTopLine, lTopColumn, True)
    If (indentChange = 0) Then
        ' If we don't change the indent, we are done
        Return
    End If

    If (lBottomLine = lTopLine) Then
        If (indentChange > 0) Then
            objSel.StartOfLine()
        Else
            objSel.StartOfLine()
            objSel.WordRight()
        End If
    End If
    objSel.Indent(indentChange)

    ' Since the selected text has changed column, adjust the columns accordingly:
    ' restore the cursor to original position and selection
    Dim lNewBottomColumn As Long = (lBottomColumn + indentChange)
    Dim lNewTopColumn As Long = (lTopColumn + indentChange)
    ' ensure that we we still on the page.
    ' The "or" clause makes it so if we were at the left edge of the line, we remain on the left edge.
    If ((lNewBottomColumn < 2) Or (lBottomColumn = 1)) Then
        ' Single line selections, or a bottomColumn that is already at 1 may still have a new BottomColumn of 1
        If ((lTopLine = lBottomLine) Or (lBottomColumn = 1)) Then
            lNewBottomColumn = 1
        Else
            ' If we have multiple lines selected, don't allow the bottom edge to touch the left column,
            ' or the next move will ignore that bottom line.
            lNewBottomColumn = 2
        End If
    End If
    If ((lNewTopColumn < 2) Or (lTopColumn = 1)) Then
        lNewTopColumn = 1
    End If

    ' restore the selection to the modified selection
    objSel.MoveToLineAndOffset(lBottomLine, lNewBottomColumn)
    objSel.MoveToLineAndOffset(lTopLine, lNewTopColumn, True)
End Sub


'' This method counts the indentation changes within the text provided as the paramter
Function CountIndentations(ByVal text As String) As Integer
    Dim indent As Integer = 0
    While (Text.Length > 0)
        If (Text.StartsWith("//")) Then
            Dim endOfLine As Integer = Text.IndexOf("\n", 2)
            If (Equals(endOfLine, -1)) Then
                ' The remaining text is all on one line, so the '//' terminates our search
                ' Ignore the rest of the text
                Exit While
            End If
            ' continue looking after the end of line
            Text = Text.Substring(endOfLine + 1)
        End If

        If (Text.StartsWith("/*")) Then
            Dim endComment As Integer = Text.IndexOf("*/", 2)
            If (Equals(endComment, -1)) Then
                ' This comment continues beyond the length of this line.
                ' Ignore the rest of the text
                Exit While
            End If
            ' continue looking after the end of this comment block
            Text = Text.Substring(endComment + 1)
        End If

        If (Text.StartsWith("{")) Then
            indent = indent + 1
        Else
            If (Text.StartsWith("}")) Then
                indent = indent - 1
            End If
        End If
        Text = Text.Substring(1)
    End While
    Return indent
End Function
Posted
Updated 21-Feb-17 22:10pm
v3
Comments
Ralf Meier 22-Feb-17 1:07am    
You want to move the selected Line inside a TextBox ?
How many Lines do you have inside your TextBox ?
Do you know, that you originally give only one string to the TextBox and the different Lines are resulting from CR-LF's between parts of the String ?
Member 10974007 22-Feb-17 1:17am    
intresting :)

i just wanna move a line up and down
multiples lines it contains ascii up to 32 chars..

just like Visual Studio Code editor :)
this function is really great :)
Ralf Meier 22-Feb-17 2:47am    
If you reply to my comment I will get a Notification ...

So ... what do you exactly want to do ?
I would suggest to create a customized TextBox which has the behaviour you want.
Are you familiar with this ?

I'll get you started...

Get the index of the caret in the TextBox:
VB
Dim caretIndex As Integer = textBox.SelectionStart
Get the line number from the caret index:
VB
Dim lineNumber As Integer = textBox.GetLineFromCharIndex(caretIndex)
Get the character index in the current line:
VB
Dim characterXY As Point = textBox.GetPositionFromCharIndex(caretIndex)
Dim characterIndex As Integer = textBox.GetCharIndexFromPosition(characterXY)
The rest is up to you.

Edit: I'll help you a little with a function to find all the new lines (or any character/text)
VB
Public Function AllIndexesOf(str As String, searchstring As String) As List(Of Integer)
    Dim index As Integer = str.IndexOf(searchstring)
    Dim indexes As List(Of Integer) = New List(Of Integer)()
    While index <> -1
        indexes.Add(index)
        index = str.IndexOf(searchstring, index + searchstring.Length)
    End While
    Return indexes
End Function
To use:
VB
Dim text = "blah blah blah blah " + vbCrLf +
    "blah blah blah blah blah blah blah blah blah blah " + vbCrLf +
    "blah blah blah blah blah blah blah blah blah blah " + vbCrLf +
    "blah blah blah blah blah blah blah blah blah blah "
Dim indexes As List(Of Integer) = AllIndexesOf(text, vbCrLf)
 
Share this answer
 
v3
Comments
Member 10974007 22-Feb-17 0:28am    
http://stackoverflow.com/questions/313462/visual-studio-hotkeys-to-move-line-up-down-and-move-through-recent-changes/313553#313553

here is a article but i dint understand
how to fix ?
Graeme_Grant 22-Feb-17 0:29am    
Do you know how to use the Debbuger in Visual Studio?

When using someone else code, you should not use it until you understand what it does.

If I were to work on this I would set break points in the code and step through each line to see what the problem could be. This is what you need to do to fix it.

[edit:] when I moved your extra code (please update the question and not put it in the reply), the code is incomplete. Please update your question with the missing code if you want others to look at it.
Graeme_Grant 22-Feb-17 0:45am    
This [url for the stack overflow answer] is about extending the Visual Studio IDE, not for working with a TextBox control. This is why you can't get it to work.
Member 10974007 22-Feb-17 1:12am    
can u improve it ?
Graeme_Grant 22-Feb-17 1:17am    
You can't improve it, it needs to be scrapped as it is non-relevant (for VS IDE and not a TextBox control) and rewritten from scratch.

Ralf has given you some pointers and I have shown you how to identify which line you are on.

Additionally, in your Form1_KeyDown you are not checking if the ALT key is held down when the arrow keys are used. Also, this code should exist in the TextBox1_KeyDown event handler and not the Form's.

FWIW, programming is writing code, not getting someone else to write it for you for free. It is about time that you get a good book or enroll in a course and learn.
Quote:
How to move a line up / down with alt + arrow_up and alt + arrow_down

In a textbox, the sequence is select line, cut selection, move cursor, paste clipboard.

When you don't understand what your code is doing or why it does what it does, the answer is debugger.
Use the debugger to see what your code is doing. Just set a breakpoint and see your code performing, the debugger allow you to execute lines 1 by 1 and to inspect variables as it execute, it is an incredible learning tool.

Debugger - Wikipedia, the free encyclopedia[^]
Mastering Debugging in Visual Studio 2010 - A Beginner's Guide[^]

The debugger is here to show you what your code is doing and your task is to compare with what it should do.
There is no magic in the debugger, it don't find bugs, it just help you to. When the code don't do what is expected, you are close to a bug.
 
Share this answer
 
Because we are here to help ...

If I understood the requirement in the right way this TextBox would help :
VB
Public Class Edit_MLTextbox
    Inherits TextBox

    Sub New()
        MyBase.Multiline = True
    End Sub

    Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
        Dim myKey As System.Windows.Forms.Keys = e.KeyCode
        Dim myAltPressed As Boolean = e.Alt
        Dim myLine As Integer = -1

        If myAltPressed AndAlso (Me.SelectionStart >= 0) Then
            myLine = Me.GetLineFromCharIndex(Me.SelectionStart)
            If myLine <> -1 Then
                If (myKey = Keys.Add) And (myLine < Me.Lines.Count - 1) Then
                    XChange(Me.Text, Me.Lines(myLine), Me.Lines(myLine + 1))
                    e.Handled = True
                ElseIf (myKey = Keys.Subtract) And (myLine > 0) Then
                    XChange(Me.Text, Me.Lines(myLine), Me.Lines(myLine - 1))
                    e.Handled = True
                End If
            End If
        End If

        MyBase.OnKeyDown(e)
    End Sub

    Private Sub XChange(ByRef sourceText As String, ByRef xchg1 As String, xchg2 As String)
        sourceText = sourceText.Replace(xchg1, Chr(1))
        sourceText = sourceText.Replace(xchg2, Chr(2))
        sourceText = sourceText.Replace(Chr(1), xchg2)
        sourceText = sourceText.Replace(Chr(2), xchg1)
    End Sub

End Class
 
Share this answer
 
Comments
Member 10974007 22-Feb-17 9:30am    
font problesm in this
Ralf Meier 22-Feb-17 10:49am    
I don't understand what you mean ...
Member 10974007 22-Feb-17 22:24pm    
full codes on request :)
as am new to vb am having full errors
Message 1

The designer cannot process the code at line 25:
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
The code within the method 'InitializeComponent' is generated by the designer and should not be manually modified.
Ralf Meier 23-Feb-17 1:33am    
I'm sorry ... I could not follow you ...
This Error-Message doesn't belong to my Control.
I would suggest the following :
- create a new application and insert my Control (the code from this Solution) and look how it works
- look what is going wrong in your application
- integrate my Control (if it is working like you want) into your application

...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900