How to Set BackColor of Inactive Control - vb.net

I have a form that contains several Textboxes and Comboboxes. I have set active control's back color property to skyblue. I want to set the back color of all textboxes and comboboxes to white while they are not active.

There's a Right Way and a wrong way to do this. You are asking for the wrong way. The right way is to derive your own class from TextBox and override the OnEnter and OnLeave methods. Repeat for ComboBox.
But you ask for the wrong way and you are probably trying to add this feature too late so we'll have to slug it out by finding the controls back at runtime. Add a constructor to your form class and make it look like:
Public Sub New()
InitializeComponent()
FindControls(Me.Controls)
End Sub
Private Sub FindControls(ctls As Control.ControlCollection)
For Each ctl As Control In ctls
Dim match As Boolean
If TypeOf ctl Is TextBoxBase Then match = True
If TypeOf ctl Is ComboBox Then
Dim combo = DirectCast(ctl, ComboBox)
If combo.DropDownStyle <> ComboBoxStyle.DropDownList Then match = True
End If
If match Then
AddHandler ctl.Enter, AddressOf ControlEnter
AddHandler ctl.Leave, AddressOf ControlLeave
End If
FindControls(ctl.Controls)
Next
End Sub
Private controlColor As Color
Private Sub ControlEnter(sender As Object, e As EventArgs)
Dim ctl = DirectCast(sender, Control)
controlColor = ctl.BackColor
ctl.BackColor = Color.AliceBlue
End Sub
Private Sub ControlLeave(sender As Object, e As EventArgs)
Dim ctl = DirectCast(sender, Control)
ctl.BackColor = controlColor
End Sub

Related

Clear focused textbox in multiple textboxes in vb.net using delete key

I want a good example of clearing focused textbox among multiple textboxes using delete key. Please help me providing vb.net code.
The public sub is as such :
Public Sub EmptyTxt(ByVal Frm As Form)
Dim Ctl As Control
For Each Ctl In Frm.Controls
'If TypeOf Ctl Is TextBox Then Ctl.Text = ""
Next
End Sub
Then I call this sub from delete keydown event. But it clears all textboxes rather than clearing the focused one.
There's an easier way to do that.
Simply assign all the textbox keyDown events to the same handler. In that handler, cast sender to a textbox and clear it.
Private Sub Form1_Load (sender As Object, e As EventArgs) Handles MyBase.Load
For Each tb As TextBox In Controls.OfType(Of TextBox)
AddHandler tb.KeyDown, AddressOf TbKeyDown
Next
End Sub
Private Sub TbKeyDown (sender As Object, e As KeyEventArgs)
Dim tb = CType(sender, TextBox)
If e.KeyCode = Keys.Delete Then
tb.Clear()
End If
End Sub

ContextMenuStrip selected item lost in UserControl

I have a VB.NET User Control which is embedded into another User Control and that into a form. The inner User Control has a contextmenustrip triggered by a DataGridView row click. This successfully activates the event handler (I see the "OK" message), but the sender does not send the selected item (I don't see the other MsgBox messages). Here is the code:
Public CMSV As ContextMenuStrip
Private grdSourceViewerCurrentRow As Long
Public Sub grdSourceViewer_RowHeaderMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles grdSourceViewer.RowHeaderMouseClick
'code to review/edit source details
Select Case e.Button
Case Windows.Forms.MouseButtons.Right
grdSourceViewerCurrentRow = e.RowIndex 'retain for downstream code
CMSV = New ContextMenuStrip
AddHandler CMSV.MouseClick, AddressOf SourceViewDocumentationEdit
CMSV.Items.Add("Edit")
CMSV.Items.Add("Transfer to Evidence")
Dim Pt As Point = New Point()
Pt.X = grdSourceViewer.PointToClient(Cursor.Position).X
Pt.Y = grdSourceViewer.PointToClient(Cursor.Position).Y + 20
CMSV.Show(sender, Pt)
Case Windows.Forms.MouseButtons.Left
Exit Sub
Case Else
Exit Sub
End Select
End Sub
Public Sub SourceViewDocumentationEdit()
MsgBox("OK") 'I can see it reaches here
Dim cc As ToolStripItemCollection = CMSV.Items
Dim SelectedItem As Integer = -1
Dim SelectedValue As String = ""
For i As Integer = 0 To cc.Count - 1
If cc.Item(i).Selected Then
SelectedItem = i
SelectedValue = cc.Item(SelectedItem).Text
Exit For
End If
Next
Select Case SelectedValue
Case "Edit"
MsgBox("Edit code here")
Case "Transfer to Evidence"
MsgBox("Transfer code here")
End Select
End Sub
What is wrong here? Why am I losing the info about the item that was clicked?
Why are you recreating the menu each time?
At any rate, store the ToolStripMenuItem returned by CMSV.Items.Add() and wire that up instead.
Simplified example:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
CMSV = New ContextMenuStrip
Dim TSMI As ToolStripMenuItem
TSMI = CMSV.Items.Add("Edit")
AddHandler TSMI.Click, AddressOf TSMI_Click
TSMI = CMSV.Items.Add("Transfer to Evidence")
AddHandler TSMI.Click, AddressOf TSMI_Click
' ...
End Sub
Private Sub TSMI_Click(sender As Object, e As EventArgs)
Dim TSMI As ToolStripMenuItem = DirectCast(sender, toolstripmenuitem)
Select Case TSMI.Text
Case "Edit"
Debug.Print("...Edit Code...")
' use "grdSourceViewerCurrentRow " in here?
Case "Transfer to Evidence"
Debug.Print("...Transfer to Evidence Code...")
' use "grdSourceViewerCurrentRow " in here?
End Select
End Sub
You need to use a ToolStripMenuItem and not just a string. Then you can add the handler for it's click event.
Dim tsmi As New ToolStripMenuItem
tsmi.Text = "Edit"
AddHandler tsmi.Click, AddressOf ItemClicked
CMSV.Items.Add(tsmi)
Then the event sub:
Private Sub ItemClicked(sender As Object, e As EventArgs)
'item clicked
'sender object would be the ToolStripMenuItem
End Sub

Trapping WM_SETFOCUS in WindProc VB.NET

I have a user control that inherits from a base user control class. On the user control that inherits this, I place a series of textboxes. At runtime, I need to know when each control gets focus and loses focus. To do this, I overrode WndProc in the base class, and am attempting to capture the messages there. The problem I'm having is that I never receive WM_SETFOCUS or WM_KILLFOCUS within the message loop.
This is the WndProc:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case WM_SETFOCUS
Debug.WriteLine(m.ToString())
Case WM_KILLFOCUS
Debug.WriteLine(m.ToString())
Case Else
Debug.Print("OTHER: " + m.ToString())
End Select
MyBase.WndProc(m)
End Sub
I get a whole bunch of message for getting text and some other stuff, so I know that I'm getting there. It just never stops on WM_SETFOCUS or WM_KILLFOCUS.
What am I not doing correctly.
Quick example of wiring up all TextBoxes in the UserControl:
Public Class UserControl1
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles Me.Load
WireTBs(Me)
End Sub
Private Sub WireTBs(ByVal cont As Control)
For Each ctl As Control In cont.Controls
If TypeOf ctl Is TextBox Then
Dim TB As TextBox = DirectCast(ctl, TextBox)
AddHandler TB.GotFocus, AddressOf TB_GotFocus
AddHandler TB.LostFocus, AddressOf TB_LostFocus
ElseIf ctl.HasChildren Then
WireTBs(ctl)
End If
Next
End Sub
Private Sub TB_GotFocus(sender As Object, e As EventArgs)
Dim TB As TextBox = DirectCast(sender, TextBox)
' ... do something with "TB" ...
Debug.Print("GotFocus: " & TB.Name)
End Sub
Private Sub TB_LostFocus(sender As Object, e As EventArgs)
Dim TB As TextBox = DirectCast(sender, TextBox)
' ... do something with "TB" ...
Debug.Print("LostFocus: " & TB.Name)
End Sub
End Class

Iterate Through Devexpres TextEdit Controls in VB.NET

Could someone help iterating through DevExpress TextEdit controls within an XTRAFORM in vb.net?
What I am actually trying to do is to intercept any value changes at FormClosing event by using EditValue and OldEditValue properties.
I meight need to tell that my controls are contained in XtraTab and XtraPanel Containers.
the following is what I tried:
Public Function TextEditChangesOccured(frm As XtraForm) As Boolean
Dim result As Boolean
For Each ctrl As BaseEdit In frm.Controls
If TypeOf ctrl Is TextEdit Then
If ctrl.EditValue <> ctrl.OldEditValue Then
result = True
Else
result = False
End If
End If
Next
Return result
End Function
Private Sub MyXtraForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If TextEditChangesOccured(Me) Then
DevExpress.XtraEditors.XtraMessageBox.Show("Changes have occured!", My.Application.Info.AssemblyName, MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Sub
but it says unable to cast XtraTab control to TextEdit control.
Your help will be much appreciated.
To make your code works just change your code snippet as follows:
Public Function TextEditChangesOccured(container As Control) As Boolean
Dim result As Boolean
For Each ctrl As Control In container.Controls
Dim bEdit As BaseEdit = TryCast(ctrl, BaseEdit)
If bEdit IsNot Nothing Then
Dim tEdit As TextEdit = TryCast(ctrl, TextEdit)
If tEdit IsNot Nothing Then
result = result Or (bEdit.EditValue <> bEdit.OldEditValue)
End If
Else
result = result Or TextEditChangesOccured(ctrl)
End If
Next
Return result
End Function
To detect changes for all the editors within a Form use the following approach:
Partial Public Class Form1
Inherits Form
Public Sub New()
InitializeComponent()
SubscribeTextEditValueChanged(Me)
End Sub
Private Sub SubscribeTextEditValueChanged(ByVal container As Control)
For Each ctrl As Control In container.Controls
Dim tEdit As TextEdit = TryCast(ctrl, TextEdit)
If tEdit IsNot Nothing Then
AddHandler tEdit.EditValueChanged, AddressOf tEdit_EditValueChanged
Else
SubscribeTextEditValueChanged(ctrl)
End If
Next ctrl
End Sub
Private IsEditValueChanged As Boolean
Private Sub tEdit_EditValueChanged(ByVal sender As Object, ByVal e As EventArgs)
IsEditValueChanged = True
End Sub
Protected Overrides Sub OnClosing(ByVal e As CancelEventArgs)
If IsEditValueChanged Then
' do some stuff
End If
MyBase.OnClosing(e)
End Sub
End Class

how to keep the selected checkbox when the form is close?

i got some checkbox and i want to retain the selected ones when i reopen the form.
here's what i done almost but it only returns the very first selected checkbox only..
For Each strItm As String In str
For Each ctl As Control In Me.Controls
If TypeOf ctl Is CheckBox Then
If ctl.Text = strItm Then
Dim cb As CheckBox = DirectCast(ctl, CheckBox)
cb.Checked = True
End If
End If
Next
Next
and anyone help me out. tnx in advance. more power.
An easy way is to create a global bool variable for each check box that holds true when its check box is checked and false when it's not. Then when you close your form those variables will keep their values. Once you re-open the form you can set the checked property back matching those variables through the form Load event
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
checkbo1.checked = globalVar1
checkbo2.checked = globalVar2
checkbo3.checked = globalVar3
End Sub
in the ParentForm:
Dim frm As New ChildForm
frm.ShowDialog()
In the ChildForm
Public Shared Chk1 As Boolean
Private Sub ChildForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CheckBox1.Checked = Chk1
End Sub
Also you need to update the vaule here when changed:
If ctl.Text = strItm Then
Dim cb As CheckBox = DirectCast(ctl, CheckBox)
cb.Checked = True
Chk1 = True
End If