locked
TextBox SelectAll does not seem to highlight the text from GotFocus? RRS feed

  • Question

  • Hi All,

    When I click the mouse on each textbox the text does not get selected. It seems it should get selected when the focus changes after clicking the textbox.

    If I put a break in the gotfocus sub it is firing, and if I continue the text is highlighted. But when not using the break in gotfocus the text does not get highlighted. Sometimes the text seems to flash a highlight. Something must be unhighlighting the text?

    If I put select all in the mousedown event, all the text is selected when first clicked. However, then one cannot unselect the text with the mouse, or click to place the caret in the middle of the text string.

    The behavior I want is to highlight the text when the textbox is first clicked or tabbed to. Then if you click again on the selected text highlight, the text to the left of the mouse click is highlighted, or click the end of the string then all the text is unselected. Or similar.

    Thanks.

    Public Class Form5
        Private WithEvents TextBox1 As New TextBox With {.Parent = Me, .Location = New Point(50, 30), .Text = "33.3333"}
        Private WithEvents TextBox2 As New TextBox With {.Parent = Me, .Location = New Point(50, 70), .Text = "33.3333"}
    
        Private Sub TextBox1_GotFocus(sender As Object, e As EventArgs) Handles TextBox1.GotFocus
    
            TextBox1.SelectAll()
        End Sub
    
        Private Sub TextBox2_GotFocus(sender As Object, e As EventArgs) Handles TextBox2.GotFocus
            TextBox2.SelectAll()
        End Sub
    
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            TextBox1.HideSelection = False
            TextBox2.HideSelection = False
        End Sub
    End Class

    Wednesday, November 16, 2016 6:06 PM

Answers

  • How about something like this?


     Private Sub TextBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles TextBox1.MouseClick
    
            If (e.Button = Windows.Forms.MouseButtons.Left) Then
                If booTextBox1ClickedOnce = False Then
                    'Must selectall
                    TextBox1.SelectAll()
                    booTextBox1ClickedOnce = True
                    Debug.Print("Mouse SelectAll - full selection")
                Else
                    If booTB1CaretPosition = False Then
                        TextBox1.SelectionStart = TextBox1.GetCharIndexFromPosition(e.Location) + 1
                        booTextBox1ClickedOnce = False
                        Debug.Print("Caret goes to last position")
                        booTB1CaretPosition = True
                    Else
                        Debug.Print("Enabling full selection again")
                        booTB1CaretPosition = False
                        booTextBox1ClickedOnce = False
                    End If
                End If
            End If
    
        End Sub
    Private Sub TextBox1_GotFocus(sender As Object, e As EventArgs) Handles TextBox1.GotFocus
            TextBox1.SelectAll()
            Debug.Print("GotFocus")
        End Sub
        Private Sub TextBox1_LostFocus(sender As Object, e As EventArgs) Handles TextBox1.LostFocus
            TextBox1.DeselectAll()
            Debug.Print("LostFocus")
        End Sub



    • Edited by Cyrille Précetti Wednesday, November 16, 2016 6:54 PM Added the Got and Lost Focus
    • Marked as answer by tommytwotrain Wednesday, November 16, 2016 11:02 PM
    Wednesday, November 16, 2016 6:46 PM
  • Well sorry about the expression...

    I meant to add the behavior to a Class, don't know much about custom Controls.

    The way I'd set it up is with a Constructor taking parameters to specify the expected behavior:

    Private WithEvents MyCustomTB As New clsCustomTextBox(True) With {.Parent = Me, .Location = New Point(50, 110), .Text = "123456"}

    and the class:

    Public Class clsCustomTextBox
        Inherits TextBox
    
        Private booSelectOnClickBehavior As Boolean = False
    
        Private booTextBox1ClickedOnce As Boolean = False
        Private booTB1CaretPosition As Boolean = False
    
    'Constructor with one Optional to set the SelectOnClick behavior. Could be more than one special behavior with each having a parameter
        Public Sub New(Optional ByVal SelectOnClikBehavior As Boolean = False)
            If SelectOnClikBehavior = False Then
                booSelectOnClickBehavior = False
            Else
                booSelectOnClickBehavior = True
            End If
    
        End Sub
    
        Private Sub Me_Enter(sender As Object, e As EventArgs) Handles Me.Enter
            Me.SelectAll()
            Debug.Print("TextBox Enter")
        End Sub
        Private Sub Me_Leave(sender As Object, e As EventArgs) Handles Me.Leave
            Me.DeselectAll()
            Debug.Print("TextBox Leave")
        End Sub
    
        Private Sub clsCustomTextBox_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    
            If booSelectOnClickBehavior = True Then
                If (e.Button = Windows.Forms.MouseButtons.Left) Then
                    If booTextBox1ClickedOnce = False Then
                        'Must selectall
                        Me.SelectAll()
                        booTextBox1ClickedOnce = True
                        Debug.Print("Mouse SelectAll - full selection")
                    Else
                        If booTB1CaretPosition = False Then
                            Me.SelectionStart = Me.GetCharIndexFromPosition(e.Location) + 1
                            booTextBox1ClickedOnce = False
                            Debug.Print("Caret goes to last position")
                            booTB1CaretPosition = True
                        Else
                            Debug.Print("Enabling full selection again")
                            booTB1CaretPosition = False
                            booTextBox1ClickedOnce = False
                        End If
                    End If
                End If
            End If
        End Sub
    
    
    End Class
    It seems to work perfectly with Enter and Leave...



    Wednesday, November 16, 2016 9:39 PM

All replies

  • How about something like this?


     Private Sub TextBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles TextBox1.MouseClick
    
            If (e.Button = Windows.Forms.MouseButtons.Left) Then
                If booTextBox1ClickedOnce = False Then
                    'Must selectall
                    TextBox1.SelectAll()
                    booTextBox1ClickedOnce = True
                    Debug.Print("Mouse SelectAll - full selection")
                Else
                    If booTB1CaretPosition = False Then
                        TextBox1.SelectionStart = TextBox1.GetCharIndexFromPosition(e.Location) + 1
                        booTextBox1ClickedOnce = False
                        Debug.Print("Caret goes to last position")
                        booTB1CaretPosition = True
                    Else
                        Debug.Print("Enabling full selection again")
                        booTB1CaretPosition = False
                        booTextBox1ClickedOnce = False
                    End If
                End If
            End If
    
        End Sub
    Private Sub TextBox1_GotFocus(sender As Object, e As EventArgs) Handles TextBox1.GotFocus
            TextBox1.SelectAll()
            Debug.Print("GotFocus")
        End Sub
        Private Sub TextBox1_LostFocus(sender As Object, e As EventArgs) Handles TextBox1.LostFocus
            TextBox1.DeselectAll()
            Debug.Print("LostFocus")
        End Sub



    • Edited by Cyrille Précetti Wednesday, November 16, 2016 6:54 PM Added the Got and Lost Focus
    • Marked as answer by tommytwotrain Wednesday, November 16, 2016 11:02 PM
    Wednesday, November 16, 2016 6:46 PM
  • Tommy,

    Just as a FYI, the event you're using (.GotFocus) really isn't a good choice:

    https://msdn.microsoft.com/en-us/library/system.windows.forms.control.gotfocus(v=vs.110).aspx

    As stated there:

    "The GotFocusand LostFocusevents are low-level focus events that are tied to the WM_KILLFOCUS and WM_SETFOCUS Windows messages. Typically, the GotFocusand LostFocusevents are only used when updating UICuesor when writing custom controls. Instead the Enterand Leaveevents should be used for all controls except the Formclass, which uses the Activatedand Deactivateevents. For more information about the GotFocusand LostFocusevents, see the WM_SETFOCUSandWM_KILLFOCUStopics."

    For what it's worth. :)


    "Everybody in this country should learn how to program a computer... because it teaches you how to think." (Steve Jobs)

    Wednesday, November 16, 2016 7:13 PM
  • How about something like this?


     Private Sub TextBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles TextBox1.MouseClick
    
            If (e.Button = Windows.Forms.MouseButtons.Left) Then
                If booTextBox1ClickedOnce = False Then
                    'Must selectall
                    TextBox1.SelectAll()
                    booTextBox1ClickedOnce = True
                    Debug.Print("Mouse SelectAll - full selection")
                Else
                    If booTB1CaretPosition = False Then
                        TextBox1.SelectionStart = TextBox1.GetCharIndexFromPosition(e.Location) + 1
                        booTextBox1ClickedOnce = False
                        Debug.Print("Caret goes to last position")
                        booTB1CaretPosition = True
                    Else
                        Debug.Print("Enabling full selection again")
                        booTB1CaretPosition = False
                        booTextBox1ClickedOnce = False
                    End If
                End If
            End If
    
        End Sub
    Private Sub TextBox1_GotFocus(sender As Object, e As EventArgs) Handles TextBox1.GotFocus
            TextBox1.SelectAll()
            Debug.Print("GotFocus")
        End Sub
        Private Sub TextBox1_LostFocus(sender As Object, e As EventArgs) Handles TextBox1.LostFocus
            TextBox1.DeselectAll()
            Debug.Print("LostFocus")
        End Sub



    Cy,

    Yes that seems to work I tested a bit and used tabs etc.

    Its just a pain. I was am hoping to find something more built in or the "proper" way so it works. Also from past experience if one of the flags somehow gets off etc. I have maybe 10 dialogs with 3 or more textboxes so...

    Selectall seems to not want to let go. I guess I will also try the whats it called... selectstartindex or something and etc see if it behaves differently.

     

    Wednesday, November 16, 2016 8:11 PM
  • Tommy,

    Just as a FYI, the event you're using (.GotFocus) really isn't a good choice:

    https://msdn.microsoft.com/en-us/library/system.windows.forms.control.gotfocus(v=vs.110).aspx

    As stated there:

    "The GotFocusand LostFocusevents are low-level focus events that are tied to the WM_KILLFOCUS and WM_SETFOCUS Windows messages. Typically, the GotFocusand LostFocusevents are only used when updating UICuesor when writing custom controls. Instead the Enterand Leaveevents should be used for all controls except the Formclass, which uses the Activatedand Deactivateevents. For more information about the GotFocusand LostFocusevents, see the WM_SETFOCUSandWM_KILLFOCUStopics."

    For what it's worth. :)


    "Everybody in this country should learn how to program a computer... because it teaches you how to think." (Steve Jobs)

    Hi Frank,

    Ok I will bite, what is the proper event?

    PS Oh, Enter and Leave nevermind.



    Wednesday, November 16, 2016 8:12 PM
  • PS Oh, Enter and Leave nevermind.

    Right. :)


    "Everybody in this country should learn how to program a computer... because it teaches you how to think." (Steve Jobs)

    Wednesday, November 16, 2016 8:22 PM
  • Why not create a CustomTextBox with the encapsulated events?
    Wednesday, November 16, 2016 8:26 PM
  • Why not create a CustomTextBox with the encapsulated events?

    Yes, well one still needs to know what the proper events etc are. :)

    Actually this is part of a textbox class that inherits textbox control. So I can easily add your example to it I am trying it now (first investigating if the behavior is the same with enter and leave instead of got and lost focus in my large app).

    My personal problem is I use the textbox class many places and ways and so I am needing to set the events in each form because some cases I don't want to do it quite exactly the same.

    But what do you mean exactly, class that inherits or do you mean custom control?

    And then finally I am not sure what an encapsulated event is. You mean use the same Boolean flags like your example?

    Wednesday, November 16, 2016 9:06 PM
  • Well sorry about the expression...

    I meant to add the behavior to a Class, don't know much about custom Controls.

    The way I'd set it up is with a Constructor taking parameters to specify the expected behavior:

    Private WithEvents MyCustomTB As New clsCustomTextBox(True) With {.Parent = Me, .Location = New Point(50, 110), .Text = "123456"}

    and the class:

    Public Class clsCustomTextBox
        Inherits TextBox
    
        Private booSelectOnClickBehavior As Boolean = False
    
        Private booTextBox1ClickedOnce As Boolean = False
        Private booTB1CaretPosition As Boolean = False
    
    'Constructor with one Optional to set the SelectOnClick behavior. Could be more than one special behavior with each having a parameter
        Public Sub New(Optional ByVal SelectOnClikBehavior As Boolean = False)
            If SelectOnClikBehavior = False Then
                booSelectOnClickBehavior = False
            Else
                booSelectOnClickBehavior = True
            End If
    
        End Sub
    
        Private Sub Me_Enter(sender As Object, e As EventArgs) Handles Me.Enter
            Me.SelectAll()
            Debug.Print("TextBox Enter")
        End Sub
        Private Sub Me_Leave(sender As Object, e As EventArgs) Handles Me.Leave
            Me.DeselectAll()
            Debug.Print("TextBox Leave")
        End Sub
    
        Private Sub clsCustomTextBox_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    
            If booSelectOnClickBehavior = True Then
                If (e.Button = Windows.Forms.MouseButtons.Left) Then
                    If booTextBox1ClickedOnce = False Then
                        'Must selectall
                        Me.SelectAll()
                        booTextBox1ClickedOnce = True
                        Debug.Print("Mouse SelectAll - full selection")
                    Else
                        If booTB1CaretPosition = False Then
                            Me.SelectionStart = Me.GetCharIndexFromPosition(e.Location) + 1
                            booTextBox1ClickedOnce = False
                            Debug.Print("Caret goes to last position")
                            booTB1CaretPosition = True
                        Else
                            Debug.Print("Enabling full selection again")
                            booTB1CaretPosition = False
                            booTextBox1ClickedOnce = False
                        End If
                    End If
                End If
            End If
        End Sub
    
    
    End Class
    It seems to work perfectly with Enter and Leave...



    Wednesday, November 16, 2016 9:39 PM
  • Cy,

    Ok I worked it in. Yes enter and leave seem the same.

    I did change the re-select after the caret select as I decided I only want one highlight on the first click. And it seemed to hit the space better without the +1 on the caret position. See where I commented those out. Just personal pref.

        If CaretPosition = False Then
              SelectionStart = GetCharIndexFromPosition(e.Location) '+ 1
              'ClickedOnce = False
              CaretPosition = True
           'Else
              'CaretPosition = False
              ' ClickedOnce = False
        End If

    Wednesday, November 16, 2016 11:02 PM
  •  Hey Tom,

     As far as i am aware,  there is not a special property that you can change or a "proper" way to do this.  This has to do with the order that the events happen and the way the textbox class handles the events internally.

     I think Cyrille is correct that you should make a small textbox class and add the functionality you want to it since you have several used in your application.

     Here is a small class i threw together that seems to function the way you want.

    Public Class TxtBx
        Inherits TextBox
        Private WithEvents Tmr As New Timer With {.Interval = 50}
        Private SelectedOnce As Boolean = False
    
        Protected Overrides Sub OnEnter(e As EventArgs)
            MyBase.OnEnter(e)
            Tmr.Enabled = Not SelectedOnce
        End Sub
    
        Protected Overrides Sub OnLeave(e As EventArgs)
            Tmr.Stop()
            SelectedOnce = False
            MyBase.OnLeave(e)
        End Sub
    
        Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
            Tmr.Stop()
            SelectedOnce = True
            Me.SelectAll()
        End Sub
    
        Protected Overrides Sub Dispose(disposing As Boolean)
            Tmr.Dispose()
            MyBase.Dispose(disposing)
        End Sub
    End Class
     


    If you say it can`t be done then i`ll try it

    Wednesday, November 16, 2016 11:19 PM
  •  Just in case you want a property to turn the option on or off,  i threw in a property called SelectAllOnEnter that you can set to True or False.  8)

    Public Class TxtBx
        Inherits TextBox
        Private WithEvents Tmr As New Timer With {.Interval = 50}
        Private SelectedOnce As Boolean = False
        Public Property SelectAllOnEnter As Boolean = False
    
        Protected Overrides Sub OnEnter(e As EventArgs)
            MyBase.OnEnter(e)
            Tmr.Enabled = (Not SelectedOnce AndAlso SelectAllOnEnter)
        End Sub
    
        Protected Overrides Sub OnLeave(e As EventArgs)
            Tmr.Stop()
            SelectedOnce = False
            MyBase.OnLeave(e)
        End Sub
    
        Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
            Tmr.Stop()
            SelectedOnce = True
            Me.SelectAll()
        End Sub
    
        Protected Overrides Sub Dispose(disposing As Boolean)
            Tmr.Dispose()
            MyBase.Dispose(disposing)
        End Sub
    End Class


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Wednesday, November 16, 2016 11:50 PM
    Wednesday, November 16, 2016 11:48 PM