Issue with combobox autocomplete - vb.net

I am trying to incorporate three comboboxes into a functional GUI which consist of textboxes, numericupdown controls and now comboboxes.
On those form I have navigation with keyboard (me.selectnextcontrol) with keys up and down.
What happens?
When I step in those GUI for first time everything work OK and I can move up/down with keyboard as expected.
Problem becomes when I edit a combobox which is in the midle of my gui and is set like this:
mycombo.AutoCompleteMode = AutoCompleteMode.SuggestAppend
mycombo.AutoCompleteSource = AutoCompleteSource.CustomSource
mycombo.AutoCompleteCustomSource = myAutoCompleteStringCollection
Problem is that when I come back to those combobox my navigation loop don't get keypress (up or down keys) anymore because combobox takes them for itselfs purpose (change index).
I try with mycombo.AutoCompleteSource = AutoCompleteSource.CustomSource after combobox_Leave but that turns off autocomplete what is not wanted.
Question is:
Is here possible to set described combobox after usage in mode like it was at the beginning of program, when it was not edited, so I can navigate with keyboard through such comboboxes at initial way but that autosuggest option remain enabled if I need to edit it again.
EDITED:
Here is simple example which shows a problem:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim tb As New TextBox
Dim cbb As New ComboBox
Dim tbb As New TextBox
Dim b1 As New Button
Dim b2 As New Button
With Me
.KeyPreview = True
.Size = New Size(350, 200)
With .Controls
.Add(tb)
With tb
.TabIndex = 0
.Location = New Point(95, 20)
.Text = "This is"
End With
.Add(cbb)
With cbb
.TabIndex = 1
.Items.AddRange(New String() {"alabama", "africa", "australia", "grenland"})
.Location = New Point(95, 50)
.Text = "an Example"
.DropDownStyle = ComboBoxStyle.DropDown
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.ListItems
End With
.Add(tbb)
With tbb
.TabIndex = 2
.Location = New Point(95, 80)
.Text = "textbox"
End With
.Add(b1)
With b1
.TabStop = False
.Location = New Point(90, 130)
.Text = "Nothing"
End With
.Add(b2)
With b2
.TabStop = False
.Location = New Point(170, 130)
.Text = "Exit"
AddHandler b2.Click, AddressOf b2_Click
End With
End With
End With
End Sub
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Up Then
e.Handled = True
Me.SelectNextControl(Me.ActiveControl, False, True, True, True)
End If
If e.KeyCode = Keys.Down Then
e.Handled = True
Me.SelectNextControl(Me.ActiveControl, True, True, True, True)
End If
End Sub
Private Sub b2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Close()
End Sub
End Class
When you start this program pass several times through all controls with key down arrow. Then stop on combobox and type letter "a", then try to navigate again with key down arrow.

Public Class Form1
Private tb As New TextBox
Private cbb As New ComboBox
Private tbb As New TextBox
Private b1 As New Button
Private b2 As New Button
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler cbb.PreviewKeyDown, AddressOf cbb_PreviewKeyDown
AddHandler tb.PreviewKeyDown, AddressOf tb_PreviewKeyDown
AddHandler tbb.PreviewKeyDown, AddressOf tbb_PreviewKeyDown
Me.Size = New Size(350, 200)
With tb
.Parent = Me
.TabIndex = 0
.Location = New Point(95, 20)
.Text = "This is"
End With
With cbb
.Parent = Me
.TabIndex = 1
.Items.AddRange(New String() {"alabama", "africa", "australia", "grenland"})
.Location = New Point(95, 50)
.Text = "an Example"
.DropDownStyle = ComboBoxStyle.DropDown
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.ListItems
End With
With tbb
.Parent = Me
.TabIndex = 2
.Location = New Point(95, 80)
.Text = "textbox"
End With
With b1
.Parent = Me
.TabStop = False
.Location = New Point(90, 130)
.Text = "Nothing"
End With
With b2
.Parent = Me
.TabStop = False
.Location = New Point(170, 130)
.Text = "Exit"
AddHandler b2.Click, AddressOf b2_Click
End With
End Sub
Private Sub tb_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs)
If e.KeyCode = Keys.Up Then tbb.Focus()
If e.KeyCode = Keys.Down Then cbb.Focus()
End Sub
Private Sub cbb_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs)
If e.KeyCode = Keys.Up Then
cbb.AutoCompleteMode = AutoCompleteMode.None
tb.Focus()
cbb.AutoCompleteMode = AutoCompleteMode.SuggestAppend
If Not cbb.Items.Contains(cbb.Text) Then cbb.Text = ""
End If
If e.KeyCode = Keys.Down Then
cbb.AutoCompleteMode = AutoCompleteMode.None
tbb.Focus()
cbb.AutoCompleteMode = AutoCompleteMode.SuggestAppend
If Not cbb.Items.Contains(cbb.Text) Then cbb.Text = ""
End If
End Sub
Private Sub tbb_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs)
If e.KeyCode = Keys.Up Then cbb.Focus()
If e.KeyCode = Keys.Down Then tb.Focus()
End Sub
Private Sub b2_Click()
Me.Close()
End Sub
End Class
I modified your code. And now, it's working. :)

Related

Finding the name of labels based on text inside its name

I’m not really sure this is possible but it would be helpful: I have quite a large grid of labels and would like to change the visibility of them based on words inside their names, for example finding a list of labels which all contain “Twentytwo” in their name and setting their visibility to false
Here is a solution based on Control.GetNextControl:
Const textToSearch = "Twentytwo" 'Text to search
Dim c As Control = Me.GetNextControl(Me, True)
Do Until c Is Nothing
'Check if c is label and its name contains "textToSearch"
If TypeOf c Is Label AndAlso c.Name.Contains(textToSearch) Then
c.Visible = False 'Hide this label
End If
c = Me.GetNextControl(c, True)
Loop
If you want to search "Twentytwo" in the label text and not in its name, replace c.Name.Containswith c.Text.Contains.
Let's say that your labels are all in one container, perhaps a Panel.
Further, let's assume you that you want only the specified labels to have .Visible = False, so the visibility is simply whether or not the label's name contains the given string.
You can select for controls of a particular type, so that there's no need to check the type of the control before using it, like this:
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
And you would call it with
SetLabelVisibility(Panel1, "Twentytwo")
Suspending the layout of the container while the updates to its child controls are being made is so that the display of it is done in one go.
Demonstration using an appropriately-sized Panel on a Form:
Public Class Form1
Dim tim As New Timer With {.Interval = 1000}
Sub CreateLabels(target As Panel)
For j = 0 To 6
For i = 0 To 4
Dim lbl = New Label With {
.Name = $"Label{j}_{i}",
.BackColor = Color.BlanchedAlmond,
.Text = i & j,
.Location = New Point(j * 40, i * 20),
.Size = New Size(38, 18),
.TextAlign = ContentAlignment.MiddleCenter
}
target.Controls.Add(lbl)
Next
Next
End Sub
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
Sub ChangeVisibleLabels(sender As Object, e As EventArgs)
Static n As Integer = 0
SetLabelVisibility(Panel1, n.ToString())
n = (n + 1) Mod 7
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateLabels(Panel1)
AddHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
RemoveHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Dispose()
End If
End Sub
End Class
Public Class Form1
Dim tim As New Timer With {.Interval = 1000}
Sub CreateLabels(target As Panel)
For j = 0 To 6
For i = 0 To 4
Dim lbl = New Label With {
.Name = $"Label{j}_{i}",
.BackColor = Color.BlanchedAlmond,
.Text = i & j,
.Location = New Point(j * 40, i * 20),
.Size = New Size(38, 18),
.TextAlign = ContentAlignment.MiddleCenter
}
target.Controls.Add(lbl)
Next
Next
End Sub
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
Sub ChangeVisibleLabels(sender As Object, e As EventArgs)
Static n As Integer = 0
SetLabelVisibility(Panel1, n.ToString())
n = (n + 1) Mod 7
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateLabels(Panel1)
AddHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
RemoveHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Dispose()
End If
End Sub
End Class
Public Class Form1
Dim tim As New Timer With {.Interval = 1000}
Sub CreateLabels(target As Panel)
For j = 0 To 6
For i = 0 To 4
Dim lbl = New Label With {
.Name = $"Label{j}_{i}",
.BackColor = Color.BlanchedAlmond,
.Text = i & j,
.Location = New Point(j * 40, i * 20),
.Size = New Size(38, 18),
.TextAlign = ContentAlignment.MiddleCenter
}
target.Controls.Add(lbl)
Next
Next
End Sub
Sub SetLabelVisibility(container As Control, namePart As String)
container.SuspendLayout()
For Each lbl In container.Controls.OfType(Of Label)
lbl.Visible = lbl.Name.Contains(namePart)
Next
container.ResumeLayout()
End Sub
Sub ChangeVisibleLabels(sender As Object, e As EventArgs)
Static n As Integer = 0
SetLabelVisibility(Panel1, n.ToString())
n = (n + 1) Mod 7
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
CreateLabels(Panel1)
AddHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
RemoveHandler tim.Tick, AddressOf ChangeVisibleLabels
tim.Dispose()
End If
End Sub
End Class

How to change BackColor of multiple Textboxes depending on the Text-property [duplicate]

This question already has answers here:
Compare Value Multiple Textbox (VB.Net)
(2 answers)
Closed 4 years ago.
I want to reduce this code as much as possible. I have about 8 textboxes and I take a lot of time, txtDrawA1 to txtDraw8. I want to change the textbox color more easily, depending on the following values, 1-2-3-4-5-6-7 - each value is assigned the same color.
Private Sub txtDrawA1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtDrawA1.TextChanged
If txtDrawA1.Text = ("1") Then
txtDrawA1.BackColor = Color.Red
ElseIf txtDrawA1.Text = ("2") Then
txtDrawA1.BackColor = Color.Aqua
ElseIf txtDrawA1.Text = ("3") Then
txtDrawA1.BackColor = Color.Chocolate
ElseIf txtDrawA1.Text = ("4") Then
txtDrawA1.BackColor = Color.BlanchedAlmond
ElseIf txtDrawA1.Text = ("5") Then
txtDrawA1.BackColor = Color.BurlyWood
ElseIf txtDrawA1.Text = ("6") Then
txtDrawA1.BackColor = Color.BlueViolet
ElseIf txtDrawA1.Text = ("7") Then
txtDrawA1.BackColor = Color.DarkBlue
End If
End Sub
Private Sub txtDrawA2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtDrawA2.TextChanged
If txtDrawA2.Text = ("1") Then
txtDrawA2.BackColor = Color.Red
ElseIf txtDrawA1.Text = ("2") Then
txtDrawA2.BackColor = Color.Aqua
ElseIf txtDrawA2.Text = ("3") Then
txtDrawA2.BackColor = Color.Chocolate
ElseIf txtDrawA2.Text = ("4") Then
txtDrawA2.BackColor = Color.BlanchedAlmond
ElseIf txtDrawA2.Text = ("5") Then
txtDrawA2.BackColor = Color.BurlyWood
ElseIf txtDrawA2.Text = ("6") Then
txtDrawA2.BackColor = Color.BlueViolet
ElseIf txtDrawA1.Text = ("7") Then
txtDrawA2.BackColor = Color.DarkBlue
End If
You can put your code in a sub and use one sub to handle multiple events from your different text boxes.
Private Sub txtDrawA1_TextChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles txtDrawA1.TextChanged,
txtDrawA2.TextChanged,
txtDrawA3.TextChanged
'I just did three you can add as many as you like make sure that you select the correct event
SetColor(sender)
End Sub
Public Sub SetColor(txtBox As TextBox)
If txtBox.Text = ("1") Then
txtBox.BackColor = Color.Red
ElseIf txtBox.Text = ("2") Then
txtBox.BackColor = Color.Aqua
ElseIf txtBox.Text = ("3") Then
txtBox.BackColor = Color.Chocolate
ElseIf txtBox.Text = ("4") Then
txtBox.BackColor = Color.BlanchedAlmond
ElseIf txtBox.Text = ("5") Then
txtBox.BackColor = Color.BurlyWood
ElseIf txtBox.Text = ("6") Then
txtBox.BackColor = Color.BlueViolet
ElseIf txtBox.Text = ("7") Then
txtBox.BackColor = Color.DarkBlue
End If
End Sub
You can do it as follows, for example.
Create one method which handles the TextChanged-event of the eight textboxes and call the second method each time to set the appropriate color.
I also added a Case Else as you may want to reset the backcolor to the default when the textbox contains another value.
Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles txtDrawA1.TextChanged,
txtDrawA2.TextChanged,
txtDrawA3.TextChanged,
txtDrawA4.TextChanged,
txtDrawA5.TextChanged,
txtDrawA6.TextChanged,
txtDrawA7.TextChanged,
txtDrawA8.TextChanged
SetTextBoxColor(DirectCast(sender, TextBox))
End Sub
Sub SetTextBoxColor(txt As TextBox)
Select Case txt.Text
Case "1"
txt.BackColor = Color.Red
Case "2"
txt.BackColor = Color.Aqua
Case "3"
txt.BackColor = Color.Chocolate
Case "4"
txt.BackColor = Color.BlanchedAlmond
Case "5"
txt.BackColor = Color.BurlyWood
Case "6"
txt.BackColor = Color.BlueViolet
Case "7"
txt.BackColor = Color.DarkBlue
Case Else
txt.BackColor = SystemColors.Window
End Select
End Sub
I'm proposing a specialized class that holds all the Color mappings in a Dictionary(Of string, Color), which exposes a method to retrive a Color based on a string value, used as the Dictionary Key.
The TextBoxColors Class GetColor() method returns a Color if the Key, corresponding to the current TextBox.Text, is defined. Otherwise, it returns Color.White.
The Event Handlers are all added, in the Form.Load() event, to all the TextBoxes which have a Name that matches a pattern: "txtDraw", here.
You could instead use the Tag property, setting it to a specific value in all the TextBoxes that need to be included in this selection.
Note that I'm supposing that all TextBoxes are child of the Form. If they are child o some other Container, just change the Me reference in For Each txtDraw As TextBox In Me.Controls to the actual Parent.
Edit:
Since your using Visual Studio 2008, the Lambda in the AddHandler statement is not supported. Code modified to comply with the (very old) VB.Net version. You need a reference to System. Linq and the Framework version must be 3.5 or newer (to support the OfType and Where extensions).
Public Class TextBoxColors
Private ColorTable As Dictionary(Of String, Color) = New Dictionary(Of String, Color)()
Public Sub New()
ColorTable.Add("1", Color.Red)
ColorTable.Add("2", Color.Aqua)
ColorTable.Add("3", Color.Chocolate)
ColorTable.Add("4", Color.BlanchedAlmond)
ColorTable.Add("5", Color.BurlyWood)
ColorTable.Add("6", Color.BlueViolet)
ColorTable.Add("7", Color.DarkBlue)
End Sub
Public Function GetColor(ColorMap As String) As Color
Return If(ColorTable.Keys.Contains(ColorMap), ColorTable(ColorMap), Color.White)
End Function
End Class
Private txtColor As TextBoxColors = New TextBoxColors()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each txtDraw As TextBox In Me.Controls.OfType(Of TextBox).Where(Function(txt) txt.Name.StartsWith("txtDraw"))
AddHandler txtDraw.TextChanged, AddressOf Me.txtDraw_TextChanged
Next
End Sub
Protected Sub txtDraw_TextChanged(sender As Object, e As EventArgs)
Dim txtDraw As TextBox = CType(sender, TextBox)
If Not String.IsNullOrEmpty(txtDraw.Text) Then
txtDraw.BackColor = txtColor.GetColor(txtDraw.Text)
End If
End Sub

Bounded ComboBox AutoComplete Sort

I have a bounded Combobox and it's data source is sorted but it seems that auto complete re-sort its items when I start typing.
For example I use this code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable
With dt
.Columns.Add("id", GetType(Long))
.Columns.Add("Name", GetType(String))
.Rows.Add({1, "John"})
.Rows.Add({2, "Jan"})
End With
With Me.ComboBox1
.DataSource = dt
.ValueMember = "id"
.DisplayMember = "Name"
.DropDownStyle = ComboBoxStyle.DropDown
.AutoCompleteMode = AutoCompleteMode.SuggestAppend
.AutoCompleteSource = AutoCompleteSource.ListItems
End With
End Sub
Now when I type j, the Combobox suggest Jan but I want the first item John.
For unbounded Combobox, this works: How to provide automatic text completion for a ComboBox control in Visual Basic .NET or in Visual Basic 2005 and also this question is For unbounded Combobox.
I modified the code in this link and now it works as needed:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable
With dt
.Columns.Add("id", GetType(Long))
.Columns.Add("Name", GetType(String))
.Rows.Add({1, "John"})
.Rows.Add({2, "Jan"})
End With
With Me.ComboBox1
.DataSource = dt
.ValueMember = "id"
.DisplayMember = "Name"
.DropDownStyle = ComboBoxStyle.DropDown
.AutoCompleteMode = AutoCompleteMode.None
End With
End Sub
Private Sub ComboBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles ComboBox1.KeyUp
' Do nothing for some keys such as navigation keys.
If ((e.KeyCode = Keys.Back) Or
(e.KeyCode = Keys.Left) Or
(e.KeyCode = Keys.Right) Or
(e.KeyCode = Keys.Up) Or
(e.KeyCode = Keys.Delete) Or
(e.KeyCode = Keys.Down) Or
(e.KeyCode = Keys.PageUp) Or
(e.KeyCode = Keys.PageDown) Or
(e.KeyCode = Keys.Home) Or
(e.KeyCode = Keys.End)) Then
Return
End If
Dim actual As String = Me.ComboBox1.Text
Dim dt As DataTable = Me.ComboBox1.DataSource
Dim dr = dt.Select("Name like '" & actual & "%'")
If dr.Count > 0 Then
Dim found As String
With Me.ComboBox1
.DroppedDown = True
Cursor.Current = Cursors.Default 'to show the cursor again
found = dr(0)("Name")
.Text = found
.SelectionStart = actual.Length
.SelectionLength = found.Length
End With
End If
End Sub
I added this line Cursor.Current = Cursors.Default to resolve this problem.

visual basic 2015: how to change text of a dynamically created label with a button click event

I have a dynamically created tabpage where I have placed dynamically created a button and label. I'm trying to figure out how to change the label.text with the button.click event. Everything works correctly until I add in the With/End With to change the label text in the button click subroutine. This is my first try at dynamically programming (hobby of mine, so trying to learn), but I do have a specific end goal for this application. Any thoughts on how to fix this problem?
Private Sub initialize_Button()
Dim button_Mybutton As New Button
With button_Mybutton
.Name = "button_My_Button"
.AutoSize = True
.Text = "Calculate"
.Visible = True
.Top = 200
.Left = 10
End With
AddHandler button_Mybutton.Click, AddressOf Me.button_Click
Me.Controls.Add(button_Mybutton)
End Sub
Protected Sub button_Click(ByVal sender As Object, ByVal e As EventArgs)
MsgBox("Button Clicked")
With label_Test
.text = "Test Confirmed"
End With
End Sub
Private Sub label_Test_Output()
Dim label_Test As New Label
With label_Test
.Name = "label_Test"
.Top = 200
.Left = 100
.AutoSize = True
.Text = "Label Test"
.Visible = True
End With
Me.Controls.Add(label_Test)
End Sub
Move the declaration of the controls outside the methods, to the class level. Then you can access them from anywhere in the class.
Private button_Mybutton As Button
Private label_Test As Label
Private Sub initialize_Button()
button_Mybutton = New Button()
With button_Mybutton
.Name = "button_My_Button"
.AutoSize = True
.Text = "Calculate"
.Visible = True
.Top = 200
.Left = 10
End With
AddHandler button_Mybutton.Click, AddressOf Me.button_Click
Me.Controls.Add(button_Mybutton)
End Sub
Protected Sub button_Click(ByVal sender As Object, ByVal e As EventArgs)
MsgBox("Button Clicked")
If label_Test IsNot Nothing Then
With label_Test
.text = "Test Confirmed"
End With
End If
End Sub
Private Sub label_Test_Output()
label_Test = New Label()
With label_Test
.Name = "label_Test"
.Top = 200
.Left = 100
.AutoSize = True
.Text = "Label Test"
.Visible = True
End With
Me.Controls.Add(label_Test)
End Sub
You should also check if the label is created when accessing it, since there is a possibility that you can click the button before calling label_Test_Output. Added null check to handler.

Navigating with arrow keys in vb.net

I'm trying to make navigation through controls with arrow keys (up/down).
To try my example just create a new form1 and paste this code into it.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim tb As New TextBox
Dim cb As New CheckBox
Dim cbb As New ComboBox
Dim b1 As New Button
Dim b2 As New Button
With Me
.KeyPreview = True
.Size = New Size(350, 200)
With .Controls
.Add(tb)
With tb
.TabIndex = 0
.Location = New Point(95, 20)
.Text = "This is"
End With
.Add(cb)
With cb
.TabIndex = 1
.Location = New Point(95, 50)
.Checked = True
.Text = "Example checkbox"
.AutoSize = True
End With
.Add(cbb)
With cbb
.TabIndex = 2
.Location = New Point(95, 80)
.Text = "an Example"
.DropDownStyle = ComboBoxStyle.DropDownList
End With
.Add(b1)
With b1
.TabStop = False
.Location = New Point(90, 130)
.Text = "Nothing"
End With
.Add(b2)
With b2
.TabStop = False
.Location = New Point(170, 130)
.Text = "Exit"
AddHandler b2.Click, AddressOf b2_Click
End With
End With
End With
End Sub
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Up Then
e.Handled = True
Me.SelectNextControl(Me.ActiveControl, False, True, True, True)
End If
If e.KeyCode = Keys.Down Then
e.Handled = True
Me.SelectNextControl(Me.ActiveControl, True, True, True, True)
End If
End Sub
Private Sub b2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Close()
End Sub
End Class
What happens?
When starting a program and navigating with arrows there havent 'focus rect' around controls and in some situation focus "run's out" to controls with tabstop = false??
But...
If I pass once with TAB key through controls after that navigating with arrows becomes good, focus rect appear's and everything is OK.
What may be problem here?
What to do that navigating with arrows behaves a same like with tab key immediately after program starts?
I find a solution to get things working as expected "through code" here:
C# code
And here is my translation to VB.
1) In some your public module add imports...
Imports System.Runtime.InteropServices
2) Put this declarations in same module:
<DllImport("user32.dll")> _
Private Sub SystemParametersInfo(ByVal uiAction As UInteger, ByVal uiParam As UInteger, ByRef pvParam As Integer, ByVal fWinIni As UInteger)
End Sub
' Constants used for User32 calls.
Const SPI_SETKEYBOARDCUES As UInteger = &H100B
3) Put this public function in same module:
''' <summary>
''' Change the setting programmatically
''' for keyboard shortcut Issue
''' </summary>
Public Sub GetAltKeyFixed()
Dim pv As Integer = 1
' Call to systemparametersinfo to set true of pv variable.
SystemParametersInfo(SPI_SETKEYBOARDCUES, 0, pv, 0)
'Set pvParam to TRUE to always underline menu access keys,
End Sub
4) From start place of your program (say Form1) just call:
GetAltKeyFixed()
Once is enough :)