Winforms Placeholder Text is Overwritten - vb.net

I am attempting to give a winforms Textbox control placeholder text by programmatically setting the respective control's text during the GetFocus and LostFocus events. However, for whatever reason the control never reflects the updated text.
This is what I'm attempting:
Private Sub TextBoxEmail_GotFocus(ByVal sender As Object, ByVal e As EventArgs) Handles TextBoxEmail.GotFocus
Dim this As TextBox = DirectCast(sender, TextBox)
With this
If .Text = "Email Address" Then
.ForeColor = Bootstrap.Utilities.Color.TextBody
.Text = String.Empty
End If
End With
End Sub
Private Sub TextBoxEmail_LostFocus(ByVal sender As Object, ByVal e As EventArgs) Handles TextBoxEmail.LostFocus
Dim this As TextBox = DirectCast(sender, TextBox)
With this
.ForeColor = Bootstrap.Utilities.Color.TextLight
If String.IsNullOrWhiteSpace(.Text) Then
.Text = "Email Address"
End If
End With
End Sub
What is odd is that if I setup a breakpoint in the LostFocus event handler and step through the code using the F11 shortcut, it is constantly cycles through the GotFocus and LostFocus events.

It happens because you are debugging the code.
When your text box gets focus at that time GetFocus event will call unfortunately you have put a breakpoint in GetFocus as well as LostFocus event. so your form Lose the focus and that focus comes to the visual studio so LostFocus event will occur after that again after the debuging process is complete your text box get focused again so again GetFocus event will call and its process will create Cycle while you debug the code.
I hope this will help you.

Related

RichEditControl event handler, prompting to save upon form close with nothing has changed

Having an issue when closing the form and nothing has changed, it still prompts to save the form. We have a form that has multiple controls. There are a few lookup combo boxes with data. They select their data and then click a button called "view". View then brings up a few textboxes and combo boxes etc and populates with data. There is also a RichEditControl that also gets loaded. After all the data is loaded in the load event. The last line is to call the following method to set event handlers for all controls. If something has changed after that then prompt to save upon form closing.
customFunc.AddDirtyEvent(Me)
The issue is and we have test if there is no richtextbox, it works. If the only control on a form is a RichEditControl, it always prompts to save no matter what, even if nothing has changed upon load. I noticed if you have a form that has a RichEditControl, and it gets populated upon form load. Even if you call the eventhandler after that, it still prompts you to save BUT if you add the eventhandler call in the form shown event, it seems to work as it doesn't set the dirty bit again. Its almost like the events are queue at the end of the form load event. But then it goes to the shown event, the call is made there and the dirty bit doesn't get reset back to true.
Issue is in our case, we can't use a shown event, because we have a button "view" that loads all the data and populates a RichEditControl. So even if we add the event handlers after the data gets loaded in the same method, it always goes back to set the dirty bit to true. We need to somehow keep the dirty bit to false after this, so if there is no changes and they just want to view data don't prompt to save upon form closing. Below is my code.
If customFunc.IsDirty = True Then
Dim dr As DialogResult = MessageBox.Show("Do you want save changes before leaving?", "Closing Mud Report", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
If dr = Windows.Forms.DialogResult.Yes Then
SimpleButtonSave.PerformClick()
ElseIf dr = Windows.Forms.DialogResult.Cancel Then
e.Cancel = True
End If
End If
Private Sub SetIsDirty(ByVal sender As System.Object, ByVal e As System.EventArgs)
is_Dirty = True
End Sub
Public Sub AddDirtyEvent(ByVal ctrl As Control)
For Each c As Control In ctrl.Controls
If TypeOf c Is RichEditControl Then
Dim rtb As RichEditControl = CType(c, RichEditControl)
AddHandler rtb.RtfTextChanged, AddressOf SetIsDirty
End If
If c.Controls.Count > 0 Then
AddDirtyEvent(c)
End If
Next
End Sub
In your SetIsDirty method check for RichEditControl.Modified property.
Here is example:
Private Sub SetIsDirty(ByVal sender As System.Object, ByVal e As System.EventArgs)
If TypeOf sender Is RichEditControl Then
Dim rtb As RichEditControl = CType(sender, RichEditControl)
is_Dirty = is_Dirty OrElse rtb.Modified
Else
is_Dirty = True
End If
End Sub

How do I set the tabIndex for a Button at run time in WinForms?

I have a generic message box where we have a few panels in which we add controls at runtime.
Here in my form, I've already pnlBottom on which pnlButtons is there along with some other controls.
Now at run time I'm adding an OK button to pnlButtons which is there on pnlBottom. I'm not setting a TabIndex for any controls in the Designer.vb file.
I'm trying to keep the focus on the OK button using the code below, but it's not working.
For Each control As Control In Me.Controls
If TypeOf (control) Is Panel Then
Dim pnlBottons As Panel = CType(control, Panel)
If pnlBottons.Name = "pnlBottom" Then
For Each ctrl As Control In control.Controls
Dim pnlButtons As Panel = CType(ctrl, Panel)
If pnlButtons.Name = "pnlButtons" Then
For Each ctrlbtn As Control In ctrl.Controls
If TypeOf (ctrlbtn) Is Button Then
Dim textBox As Button = CType(ctrlbtn, Button)
textBox.Parent.Parent.TabIndex = 0
textBox.Parent.TabIndex = 0
textBox.TabIndex = 0
End If
Next
End If
Next
End If
End If
Next
Here I'm setting the TabIndex for pnlBottom, pnlButtons and OK button as 0.
Please suggest how to focus the OK button.
You can set the focus on a control during Form Load event using either of the following options. (Ref: How to set the focus on a control when the form loads in Visual Basic .NET or in Visual Basic 2005. The original link is broken, so use Wayback Machine.)
1- Control.Select Method
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Mybase.Load
Me.OKButton.Select()
End Sub
Focus is a low-level method intended primarily for custom control
authors. Instead, application programmers should use the Select method
or the ActiveControl property for child controls, or the Activate
method for forms.
2- Form.ActiveControl Property
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Mybase.Load
Me.ActiveControl = Me.OKButton
End Sub
3- Control.Focus Method
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Mybase.Load
Me.Show()
Me.OKButton.Focus()
End Sub
The reason that we call Me.Show() is to set forms visible to true. according to:
You can use the Control.Focus method in the Load event of the form to
set the focus on a control only after the Visible property of the form
is set to True.
In cases you can not use Me.OKButton you can find the control you want like this:
Dim control = Me.Controls.Find("OKButton", True).FirstOrDefault()
If Not control Is Nothing Then
control.Select() 'or other stuff
End If

Textbox Focus - Click versus Tab Using VB

The following code changes the properties of a textbox when it has focus and reverts the changes after losing focus. I'm having trouble with using the Enter, Leave, GotFocus, LostFocus events because they occur in different orders when clicking or tabbing to a textbox. The following code only acts as expected when tabbing between textboxes but not clicking. If I change txtBoxes_ReminderOffFocus to handle the Leave event instead of LostFocus, then it works as expected when clicking between textboxes but not tabbing.
Private Sub txtBoxes_ReminderOnFocus(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtHrsWkd.Enter, txtPayRate.Enter, txtFedTaxRate.Enter, txtStTaxRate.Enter
If sender.Text = "(Numeric Value)" Or sender.Text = "(Percentage)" Then
Debug.Print("New textbox focused onto.") 'Sets up textboxes for standard input, if they have initial reminder. Check control.enter event for more on focus orderings.
sender.Clear()
sender.TextAlign = HorizontalAlignment.Left
sender.ForeColor = Color.Black
End If
End Sub
Private Sub txtBoxes_ReminderOffFocus(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtHrsWkd.LostFocus, txtPayRate.LostFocus, txtFedTaxRate.LostFocus, txtStTaxRate.LostFocus
If sender.Text = "" Then
Debug.Print("A textbox has lost focus.")
sender.ForeColor = Color.Gray 'if textbox is empty, fills in initial "numeric value" or "percentage" reminder.
sender.TextAlign = HorizontalAlignment.Right
If sender Is txtHrsWkd Or sender Is txtPayRate Then
sender.Text = "(Numeric Value)"
Else
sender.Text = "(Percentage)"
End If
End If
End Sub
In 'txtBoxes_ReminderOffFocus'
.LostFocus event works as expected when tabbing between textboxes, not clicking.
.Leave event works as expected when clicking between textboxes, not tabbing.
Since .LostFocus works for tabbing and not clicking and .Leave works when clicking and not tabbing, can you try setting txtBoxes_ReminderOffFocus to handle both events?

vb.net Keydown event on whole form

I have a form with several controls. I want to run a specific sub on keydown event regardless any controls event.
I mean if user press Ctrl+S anywhere on form it execute a subroutine.
You should set the KeyPreview property on the form to True and handle the keydown event there
When this property is set to true, the form will receive all KeyPress,
KeyDown, and KeyUp events. After the form's event handlers have
completed processing the keystroke, the keystroke is then assigned to
the control with focus. .......... To handle keyboard
events only at the form level and not allow controls to receive
keyboard events, set the KeyPressEventArgs.Handled property in your
form's KeyPress event handler to true.
So, for example, to handle the Control+S key combination you could write this event handler for the form KeyDown event.
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles MyBase.KeyDown
If e.Control AndAlso e.KeyCode = Keys.S then
' Call your sub method here .....
YourSubToCall()
' then prevent the key to reach the current control
e.Handled = False
End If
End Sub
I've used this code in my forms before and it seems to work pretty good.
Protected Overrides Function ProcessKeyPreview(ByRef m As System.Windows.Forms.Message) As Boolean
If m.Msg = &H100 Then 'WM_KEYDOWN
Dim key As Keys = m.WParam
If key = Keys.S And My.Computer.Keyboard.CtrlKeyDown Then
'DO stuff
Return True
End If
End If
Return MyBase.ProcessKeyPreview(m)
End Function

Can't set focus on a Windows Forms textbox

I can't seem to get input focus on a textbox when a tab page first comes up (I'm using Windows Forms, VB.NET 3.5).
I have a textbox on a panel on a tab page, and I want the focus to be on the textbox when the tab page comes up. I want the user to be able to start typing immediately in the focused textbox without having to click on the textbox. I have tab stops set in the order I want and the textbox is the first tab stop. The tab stops work except that when the tab page comes up the focus is not on the textbox, i.e. the one that's first in the tab order.
In the Enter event handler of the tab page I call the Focus method of the text box, but it returns False and does nothing, no error messages. I know I can access the text box because
at the same point in the code I can set the text of the text box.
If it matters, the layout of the tab page is a little complicated:
frmFoo/TabControl1/TabPageX/Panel1/Panel2/TextBox1
I want to set the focus on TextBox1.
What's the best way to get the focus on the desired textbox?
If setting focus is the best way, why is the textbox.Focus() method failing?
I would assume you are attempting to set focus in the form load event handler? If so, you need to do a Me.Show() to actually create the onscreen controls before focus can be set. Something along the lines of:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Me.Show()
Application.DoEvents()
TextBox1.Focus()
End Sub
If you don't do the Me.Show(), the form is NOT displayed until the load event is complete.
For the tab control, handle the _SelectedIndexChanged event:
Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As System.EventArgs) _
Handles TabControl1.SelectedIndexChanged
If TabControl1.SelectedTab.Name = "TabPage1" Then
TextBox2.Focus()
End If
If TabControl1.SelectedTab.Name = "TabPage2" Then
TextBox4.Focus()
End If
You will still want to set the initial focus in the load event as shown above if the first field selected is to be the textbox on the tab control.
Try either:
Me.ActiveControl = TextBox1
or
TextBox1.Select()
Do the control.Focus() in the OnShown event. You don't need any of the DoEvents logic which didn't work for me anyway.
You Should Use Selected Event of TabControl
Private Sub TabControl1_Selected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles TabControl1.Selected
If e.TabPage.Name = "TabPage1" Then
TextBox1.Select()
End If
End Sub
As I have Checked in Both TabControl.Selected and TabPage.Enter Event can set Select TextBox. I think there is some other elements stealing focus. please varify
Any of the solutions I found online don't solve the problem when the control is on a tab page.
However, this works:
(1) set the TabIndex of the control to 0.
(2) In your code that handles the tabpage event, do the following:
SendKeys.Send("{TAB}")
If SendKeys doesn't seem to be a valid statment, make sure you have the following import at the top of your code file:
Imports System.Windows.Forms
I found that the TabControl gets the focus when the Selected event completes. To make this work I used the Paint event of the TabPage to set the focus of the desired object.
Private Sub TabChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tab1.Paint, Tab2.Paint, Tab3.Paint
Select Case sender.Name
Case "Tab1"
Textbox1.Focus()
Case "Tab2"
T3extbox2.Focus()
Case "Tab3"
Textbox3.Focus()
End Select
End Sub
Try the Activated event of the form like this:
Private Sub Form2_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
'SendKeys.Send("{TAB}") this line works too
TextBox1.Focus()
End Sub
That is guaranteed to work.
I once had the same problem but i solved it using the Me.activate() function.