Automatic SelectAll on all textboxes and numericUpDown controls on gotfocus - vb.net

I have such code to make all text in textbox selected on got_focus:
Private Sub myText_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles myText.GotFocus
myText.SelectAll()
End Sub
Is here a way in VB.NET to get that all TextBoxes and NumericUpDown controls selects his text on _GotFocus or _Enter without to explicitly set such behavior for every single control and no matter how this control gets a focus (keyboard, mouse or programmatic)?

Yes, there is and very simple.
Private Sub TextBox2_GotFocus(sender As Object, e As System.EventArgs) Handles TextBox2.GotFocus
TextBox2.Select(0, TextBox2.Text.Length)
End Sub

Public Class MyTextBox
Inherits System.Windows.Forms.TextBox
Private _focused As Boolean
Protected Overrides Sub OnEnter(e As EventArgs)
MyBase.OnEnter(e)
If MouseButtons = MouseButtons.None Then
SelectAll()
_focused = True
End If
End Sub
Protected Overrides Sub OnLeave(e As EventArgs)
MyBase.OnLeave(e)
_focused = False
End Sub
Protected Overrides Sub OnMouseUp(mevent As MouseEventArgs)
MyBase.OnMouseUp(mevent)
If Not _focused Then
If SelectionLength = 0 Then
SelectAll()
End If
_focused = True
End If
End Sub
End Class

Related

cmbComboBox.SelectionStart always returns zero irrespective of cursor location

For some reason the "SelectionStart" property behaves differently from TextBox to ComboBox.
Create a TextBox and a ComboBox. Make sure DropDownStyle = DropDown (NOT DropDownList!)
Add these Leave events (same result if you use LostFocus event):
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave
Debug.Print("Textbox: " & TextBox1.SelectionStart)
End Sub
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
Debug.Print("ComboBox: " & ComboBox1.SelectionStart)
End Sub
Now type text into each control and change focus from control to control, with the selection cursor in different places in the string.
I get this:
Textbox: 6
ComboBox: 0
Textbox: 8
ComboBox: 0
Textbox: 5
ComboBox: 0
Textbox: 4
ComboBox: 0
... and so on
When the textbox loses focus, it returns the correct SelectionStart.
When the combobox loses focus, it always returns zero.
Is there a reason, solution or reasonable workaround? I cannot seem to intercept this without creating a new variable for each combo control, and storing the SelectionStart on every click and keypress event (assuming the user might click the mouse, use arrow keys or type characters).
I just did some testing and it appears that the selection is reset between the Leave and LostFocus events as well as between the Enter and GotFocus events. I tried remembering the values on the first of each pair and restoring it on the second and it worked as desired:
Private comboBox1SelectionStart As Integer
Private comboBox1SelectionLength As Integer
Private Sub ComboBox1_Enter(sender As Object, e As EventArgs) Handles ComboBox1.Enter
comboBox1SelectionStart = ComboBox1.SelectionStart
comboBox1SelectionLength = ComboBox1.SelectionLength
End Sub
Private Sub ComboBox1_Leave(sender As Object, e As EventArgs) Handles ComboBox1.Leave
comboBox1SelectionStart = ComboBox1.SelectionStart
comboBox1SelectionLength = ComboBox1.SelectionLength
End Sub
Private Sub ComboBox1_GotFocus(sender As Object, e As EventArgs) Handles ComboBox1.GotFocus
ComboBox1.SelectionStart = comboBox1SelectionStart
ComboBox1.SelectionLength = comboBox1SelectionLength
End Sub
Private Sub ComboBox1_LostFocus(sender As Object, e As EventArgs) Handles ComboBox1.LostFocus
ComboBox1.SelectionStart = comboBox1SelectionStart
ComboBox1.SelectionLength = comboBox1SelectionLength
End Sub
You don't want to have to do that every time for every CokmboBox so you can build it into a custom control and then use that in place of the standard control:
Public Class ComboBoxEx
Inherits ComboBox
Private selectionStartTemp As Integer
Private selectionLengthTemp As Integer
Protected Overrides Sub OnEnter(e As EventArgs)
MyBase.OnEnter(e)
'Remember the current selection.
selectionStartTemp = SelectionStart
selectionLengthTemp = SelectionLength
End Sub
Protected Overrides Sub OnGotFocus(e As EventArgs)
'Restore the selection.
SelectionStart = selectionStartTemp
SelectionLength = selectionLengthTemp
MyBase.OnGotFocus(e)
End Sub
Protected Overrides Sub OnLeave(e As EventArgs)
MyBase.OnLeave(e)
'Remember the current selection.
selectionStartTemp = SelectionStart
selectionLengthTemp = SelectionLength
End Sub
Protected Overrides Sub OnLostFocus(e As EventArgs)
'Restore the selection.
SelectionStart = selectionStartTemp
SelectionLength = selectionLengthTemp
MyBase.OnLostFocus(e)
End Sub
End Class
A side-effect of this is that you will see the text selected even when the control doesn't have focus. The ComboBox has no HideSelection property like the TextBox does. If you don't like this then I'd imagine that you could find a way to make it behave like the TextBox does but that's a different question so I won't go into it here.
I think I've got it, using your idea but just setting the value in a different location.
Dim ComboSelectionStart As Integer
Private Sub cmbComboBox_KeyUp(sender As Object, e As KeyEventArgs) Handles cmbComboBox.KeyUp
'Store selection on any key press
ComboSelectionStart = cmbComboBox.SelectionStart
End Sub
Private Sub cmbComboBox_MouseClick(sender As Object, e As MouseEventArgs) Handles cmbComboBox.MouseClick
'Store selection on any mouse click
ComboSelectionStart = cmbComboBox.SelectionStart
End Sub
Private Sub cmbComboBox_Leave(sender As Object, e As EventArgs) Handles cmbComboBox.Leave
'Returns correct value here because it was not altered by LostFocus event
Debug.Print(ComboSelectionStart .ToString)
End Sub
When you modify the OnLeave() sub in the class provided by #jmcilhinney it actually works nicely.
Protected Overrides Sub OnLeave(e As EventArgs)
'Remember the current selection.
selectionStartTemp = SelectionStart
selectionLengthTemp = SelectionLength
MyBase.OnLeave(e) 'this has to go last because it modifies the SelectionStart...
End Sub

Order of KeyEvents processing in Winforms with VB.NET

I have subclassed form with 3 controls-NumericUpDown in it.
Here is main form' code:
Public Class Form1
Inherits cls_subform
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.KeyPreview = True
End Sub
Private Sub NumericUpDown1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles NumericUpDown1.KeyDown
If e.KeyCode = Keys.Enter Then
Debug.Print "Control's ENTER is pressed"
End If
End Sub
End Class
Here is simplified frm_subform code:
Public Class cls_subform
Inherits System.Windows.Forms.Form
Public Sub New()
InitializeComponent()
End Sub
Protected Overrides Sub onKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
If e.KeyCode = Keys.Enter Then
e.Handled = True
e.SuppressKeyPress = True
Debug.Print "Subclassed ENTER is pressed"
End If
MyBase.OnKeyDown(e)
End Sub
End Class
This obviously work propper.
But problem is that I would like to handle control's event handler NumericUpDown1_KeyDown FIRST. And then if it is not "handled" I would like to handle onKeyDown event handler on frm_subform.
If I set KeyPreview to False then I can catch control's event but then onKeyDown is not fired.
Is there a way to get desired functionality?
That FIRST will be fired control's _KeyDown handler and then form's onKeyDown handler?

Cancel Datetimepicker ValueChanged Event

Is there a way to cancel an event through a condition? I have tried e.cancel but it does not work. After cancelling the event the dtpAudit_From.Value must revert back to its original value.
Private Sub dtpAudit_From_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dtpAudit_From.ValueChanged
'check if two DTPs (Date time pickers) are valid
If dtpAudit_From.Value > dtpAudit_To.Value Then
MsgBox("cancel the event")
End If
End Sub
One way is to subclass the DateTimePicker and add a ValueChanging event. Here's an example:
Public Class UIDateTimePicker
Inherits DateTimePicker
Public Sub New()
Me.cachedValue = Me.Value
End Sub
Public Event ValueChanging As CancelEventHandler
Protected Overrides Sub OnValueChanged(e As EventArgs)
If (Not Me.reverting) Then
Dim evargs As New CancelEventArgs(False)
Me.OnValueChanging(evargs)
If ((Not evargs Is Nothing) AndAlso evargs.Cancel) Then
Dim value As Date = Me.Value
Me.reverting = True
Me.Value = Me.cachedValue
Else
Me.cachedValue = Value
MyBase.OnValueChanged(e)
End If
Me.reverting = False
End If
End Sub
Protected Overridable Sub OnValueChanging(e As CancelEventArgs)
RaiseEvent ValueChanging(Me, e)
End Sub
Private cachedValue As DateTime
Private reverting As Boolean
End Class
Usage
Private Sub dtpAudit_From_ValueChanging(sender As Object, e As CancelEventArgs) Handles dtpAudit_From.ValueChanging
e.Cancel = {Condition}
End Sub

SelectAll on enter to NumericUpDown control

There are people which try to solve such problem on entering to textbox. And they solved that more or less successfully.
I am trying to do same thing with NumericUpDown control by subclassing it pretty unsuccessfully.
Here is my code:
Public Class xNumericUpDown
Inherits NumericUpDown
Private _focused As Boolean
Protected Overrides Sub OnEnter(ByVal e As EventArgs)
MyBase.OnEnter(e)
If MouseButtons = MouseButtons.None Then
Me.Select(0, Me.Text.Length)
_focused = True
End If
End Sub
Protected Overrides Sub OnLeave(ByVal e As EventArgs)
MyBase.OnLeave(e)
_focused = False
End Sub
Protected Overrides Sub OnMouseUp(ByVal mevent As MouseEventArgs)
MyBase.OnMouseUp(mevent)
If Not _focused Then
If Me.Text.Length = 0 Then
Me.Select(0, Me.Text.Length)
End If
_focused = True
End If
End Sub
End Class
This selects All by entering with keyboard but dont work when selecting control with mouse.
Any help with solving that problem would be appreciated.
You will probably kick yourself, but try changing your code to this:
If Me.Text.Length > 0 Then
Me.Select(0, Me.Text.Length)
End If

Making combobox visible when it is disabled

I am disabling combobox in VB.net.
But in disable mode it not visible properly.
I tried changing both BackColor and ForeColor but it is not working.
Code :
cmbbox.BackColor = Color.FromName("Window")
or
cmbbox.ForeColor = Color.FromName("Window")
Please help
Dear Adam:
I am making my component enable false.But I want to make it viewable.You can reffer the link.This is what exacly I want but in VB.Net : A combobox that looks decent when it is disabled
To achieve disabling combobox without fading it, first change the dropdown style of the combobox to DropDownList, Then tweak with the events to achieve the goal.
Here is a piece of code by which you can achieve the same:
Public Class Form1
Dim selectindex As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ComboBox1.Items.Add("1")
ComboBox1.Items.Add("2")
ComboBox1.Items.Add("3")
ComboBox1.Items.Add("4")
selectindex = 3
ComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
ComboBox1.SelectedIndex = selectindex
End Sub
Private Sub ComboBox1_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectionChangeCommitted
ComboBox1.SelectedIndex = selectindex
End Sub
End Class
Create anew form Form1 and add a combobox to the form, then add the above code to get a readonly combobox.
Have a look at this thread which has a solution for a readonly combobox and the code is all VB.NET.
A version of their code is as follows. You'll need to but it inside a class of your own which inherits System.Windows.Forms.ComboBox
Private _ReadOnly As Boolean = False
Public Property [ReadOnly]() As Boolean
Get
Return _ReadOnly
End Get
Set(ByVal Value As Boolean)
_ReadOnly = Value
End Set
End Property
Public Overrides Function PreProcessMessage(ByRef msg As Message) As Boolean
'Prevent keyboard entry if control is ReadOnly
If _ReadOnly = True Then
'Check if its a keydown message
If msg.Msg = &H100 Then
'Get the key that was pressed
Dim key As Int32 = msg.WParam.ToInt32
'Ignore navigation keys
If key = Keys.Tab Or key = Keys.Left Or key = Keys.Right Then
'Do nothing
Else
Return True
End If
End If
End If
'Call base method so delegates receive event
Return MyBase.PreProcessMessage(msg)
End Function
Protected Overrides Sub WndProc(ByRef m As Message)
'Prevent list displaying if ReadOnly
If _ReadOnly = True Then
If m.Msg = &H201 OrElse m.Msg = &H203 Then
Return
End If
End If
'Call base method so delegates receive event
MyBase.WndProc(m)
End Sub
I've been looking for the same not long ago and ended up doing the following. You may not like it, but i'll share it in case. I am using TableLayoutPanel to arrange my controls on the form and then i am swapping the positions of the desired controls.
For example I've created the following Items:
Form1 Design
TableLayoutPanel1 (two columns, three rows)
TextBox1 Read-only = True, BackColor = White
ComboBox1 Visible = False, DropDownStyle = DropDownList, FlatStyle = Popup
Button1 (named it to Change)
Button2 (named it to Done) -> Visible = False
Runtime - Screenshots
Here is my code:
Public Class Form1
Private Sub SwapControls(tlp As TableLayoutPanel, ctr1 As Control, ctr2 As Control)
Dim ctl1pos As TableLayoutPanelCellPosition = tlp.GetPositionFromControl(ctr1)
ctr1.Visible = False
tlp.SetCellPosition(ctr1, tlp.GetPositionFromControl(ctr2))
ctr2.Visible = True
tlp.SetCellPosition(ctr2, ctl1pos)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SwapControls(TableLayoutPanel1, TextBox1, ComboBox1)
SwapControls(TableLayoutPanel1, Button1, Button2)
Label1.Select()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
SwapControls(TableLayoutPanel1, ComboBox1, TextBox1)
SwapControls(TableLayoutPanel1, Button2, Button1)
Label1.Select()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Label1.Select()
ComboBox1.SelectedIndex = 0
TextBox1.Text = ComboBox1.SelectedItem
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
TextBox1.Text = ComboBox1.SelectedItem
End Sub
End Class