Answered by:
TextBox SelectAll does not seem to highlight the text from GotFocus?

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...
- Edited by Cyrille Précetti Wednesday, November 16, 2016 9:40 PM
- Marked as answer by tommytwotrain Wednesday, November 16, 2016 11:02 PM
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.
- Edited by tommytwotrain Wednesday, November 16, 2016 8:13 PM
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...
- Edited by Cyrille Précetti Wednesday, November 16, 2016 9:40 PM
- Marked as answer by tommytwotrain Wednesday, November 16, 2016 11:02 PM
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