Setting tab stop between two panels - vb.net

I have two panels, each has several textboxes. What I want is something that seems very simple: user enter a textbox in this panel, then press Tab to jump to its 'linked' textbox in the other panel.
But, vb refuses to jump to other panel unless it finishes through all of the textboxes inside one panel, no matter what TapStop it is.
I tried to catch the tab key from a textbox, and send focus to the linked one without success: pressing Tab doesn't even fire the KeyDown nor KeyPress event.
I tried to set TabStop to the panels first, but that also fail.
So, the problem remain.. how to set tabstop.. or any similar means, to the textboxes between two panel so that when user press Tab in one panel, it will switch to the other one ?
I need the Tab key, not anyother key.

You'll have to set the TabStop property of each control on the form to False and then handle the tabbing yourself, which you can do like this:
Private Sub TextBoxes_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles TextBox6.PreviewKeyDown,
TextBox5.PreviewKeyDown,
TextBox4.PreviewKeyDown,
TextBox3.PreviewKeyDown,
TextBox2.PreviewKeyDown,
TextBox1.PreviewKeyDown
If e.KeyCode = Keys.Tab Then
Dim controls As Control() = {TextBox1, TextBox4, TextBox2, TextBox5, TextBox3, TextBox6, Button2}
Dim currentControlIndex = Array.IndexOf(controls, ActiveControl)
Dim nextControl = controls(currentControlIndex + 1)
nextControl.Select()
End If
End Sub
Every control you want to be able to Tab from must be in the Handles clause and every control that you want to be able to Tab to or from must be in the array and in the order you want to Tab to them in. You should also repeat the first control at the end of the array again, in order to wrap back to the beginning from the end.
Also note that no control will be selected by default if none of them a Tab stops, in which case you must manually Select the control you want to have focus by default in the form's Shown event handler.
EDIT: Here is a more complete example:
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'Manually focus the first control after the form is displayed.
Button1.Select()
End Sub
'Include all the controls that you want to behave as Tab stops in the Handles clause.
'The order is unimportant but ordering them you will Tab to them is not a bad idea.
Private Sub TextBoxes_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown,
TextBox1.PreviewKeyDown,
TextBox4.PreviewKeyDown,
TextBox2.PreviewKeyDown,
TextBox5.PreviewKeyDown,
TextBox3.PreviewKeyDown,
TextBox6.PreviewKeyDown,
Button2.PreviewKeyDown
If e.KeyCode = Keys.Tab Then
'This array must contain all controls to behave as Tab stops in order and the first must be repeated at the end.
Dim controls As Control() = {Button1, TextBox1, TextBox4, TextBox2, TextBox5, TextBox3, TextBox6, Button2, Button1}
'Find the currently active control in the array.
Dim currentControlIndex = Array.IndexOf(controls, ActiveControl)
'Get the next control in the manual tab order.
Dim nextControl = controls(currentControlIndex + 1)
'Focus that next control.
nextControl.Select()
End If
End Sub
That code works for the following form, where TextBox1, TextBox2 and TextBox3 are in Panel1 and TextBox4, TextBox5 and TextBox6 are in Panel2:

Related

How do you set a dynamically created panel to false in VB.net?

I have on my screen design Panel1(left half), and panel2 through 10(right half), the panels on the right half are named based on data from a database.
I need to be able to click on a button in panel1 and when I do so, I need to set visibility to false for the current panel on the right half and set visibility to true that is referenced from the button click. I know that I can do the following but I think this is just way too much overhead and there has to be a better solution than this:
For Each control In Me.Controls.OfType(Of Panel)
If control.visible = true Then
control.visible = false
exit
Next
Panel that the visibility that needs to be set to false was dynamically created so it can not just be accessed by just name, otherwise that would solve my issue easily.
I seen this bit of code elsewhere and it would make my life easier, however not sure how to implement it dynamically when the panels are created, since the name of the panels are unknown at creation.
This bit of code to be able to reference the panels directly.
Dim machinePanel As Panel = DirectCast(Me.Controls.Item("pnl" & strMTB & strMachineID), Panel)
I'm not sure what you mean but "is referenced from the button click", so I'll assume that the text of the button refers to the panel name.
Create a method that handles the visibility
Private Sub SetPanelVisibility(button As Button)
'panel that the button is in
Dim leftPanel = CType(button.Parent, Panel)
'get right panels and ignore left
Dim rightpanels = Me.Controls.OfType(Of Panel).Where(Function(x) x.Name <> leftPanel.Name)
'set visibility of each panel.
For Each panel In rightpanels
panel.Visible = panel.Name = button.Text
Next
End Sub
To call the method just pass the button in on the click event. e.g.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SetPanelVisibility(sender)
End Sub

Use a virtual Keyboard on focused Textboxes and DataGridView Cells

In my Form I have various Textboxes that I write into with an in Form keyboard I created using Buttons. I have this code in Form.Load, which uses an event handler to determine which Textbox has the Focus:
For Each control As Control In Me.Controls
If control.GetType.Equals(GetType(TextBox)) Then
Dim textBox As TextBox = control
AddHandler textBox.Enter, Sub() FocussedTextbox = textBox
End If
Next
Then I use this on each button to write a specific character:
Private Sub btnQ_Click(sender As Object, e As EventArgs) Handles btnQ.Click
If btnQ.Text = "Q" Then
FocussedTextbox.Text += "Q"
ElseIf btnQ.Text = "q" Then
FocussedTextbox.Text += "q"
End If
End Sub
Up to that point I'm good and everything works as intended. The problem is I also have a DataGridView I want to write into but can't focus on it selected cells as I do on Textboxes.
I tried this:
For Each control As Control In Me.Controls
If control.GetType.Equals(GetType(TextBox)) Then
Dim textBox As TextBox = control
AddHandler textBox.Enter, Sub() FocussedTextbox = textBox
ElseIf control.GetType.Equals(GetType(DataGridViewCell)) Then
Dim DGVC As DataGridView = control
AddHandler DGVC.CellBeginEdit, Sub() FocussedTextbox = DGVC
End If
Next
But it just selects my last Textbox.
I declared the variable FocussedTextbox as Control so it's not specific to Textbox but any control.
Any help will be greatly appreciated.
To add text to the current ActiveControl using Buttons, these Button must not steal the focus from the ActiveControl (otherwise they become the ActiveControl).
This way, you can also avoid all those FocusedTextbox = textBox etc. and remove that code.
You just need Buttons that don't have the Selectable attribute set. You can use a Custom Control derived from Button and remove ControlStyles.Selectable in its constructor using the SetStyle method:
Public Class ButtonNoSel
Inherits Button
Public Sub New()
SetStyle(ControlStyles.Selectable, False)
End Sub
End Class
Replace your Buttons with this one (or, well, just set the Style if you're already using Custom Controls).
To replace the existing Buttons with this Custom Control:
Add a new class object to your Project, name it ButtonNoSel, copy all the code above inside the new class to replace the two lines of code you find there.
Build the Project. You can find the ButtonNoSel Control in your ToolBox now. Replace your Buttons with this one.
Or, open up the Form's Designer file and replace (CTRL+H) all System.Windows.Forms.Button() related to the Virtual KeyBoard with ButtonNoSel.
Remove the existing event handlers, these are not needed anymore.
Add the same Click event handler in the Constructor of the class that hosts those Buttons (a Form or whatever else you're using).
You can then remove all those event handlers, one for each control, that you have now; only one event handler is needed for all:
Public Sub New()
InitializeComponent()
For Each ctrl As Control In Me.Controls.OfType(Of ButtonNoSel)
AddHandler ctrl.Click, AddressOf KeyBoardButtons_Click
Next
End Sub
Of course, you also don't need to add event handlers to any other control, this is all that's required.
Now, you can filter the Control types you want your keyboard to work on, e.g., TextBoxBase Controls (TextBox and RichTextBox), DataGridView, NumericUpDown etc.
Or filter only special cases that need special treatment (e.g., MonthCalendar).
To add the char corresponding to the Button pressed, you can use SendKeys.Send(): it will insert the new char in the current insertion point, so you don't need any other code to store and reset the caret/cursor position as it happens if you set the Text property of a Control.
In this example, I'm checking whether the ActiveControl is a TextBoxBase Control, then just send the char that the clicked Button holds.
If it's a DataGridView, first send F2 to enter Edit Mode, then send the char.
You could also just send a char (so, no filter would be required), but in this case, you'll replace, not add to, the existing value of that Cell.
Private Sub KeyBoardButtons_Click(sender As Object, e As EventArgs)
Dim selectedButton = DirectCast(sender, Control)
Dim keysToSend = String.Empty
If TypeOf ActiveControl Is TextBoxBase Then
keysToSend = selectedButton.Text
ElseIf TypeOf ActiveControl Is DataGridView Then
Dim ctrl = DirectCast(ActiveControl, DataGridView)
If TypeOf ctrl.CurrentCell IsNot DataGridViewTextBoxCell Then Return
SendKeys.Send("{F2}")
keysToSend = selectedButton.Text
Else
' Whatever else
End If
If Not String.IsNullOrEmpty(keysToSend) Then
SendKeys.Send(keysToSend)
End If
End Sub
► Note that {F2} is sent just once: when the Cell enters Edit Mode, the ActiveControl is a DataGridViewTextBoxEditingControl, hence a TextBox Control, handled by the TextBoxBase filter.
This is how it works (using just the code posted here):

Show ContextMenuStripItem without clicking off the current cell

I'm using an UltraGrid which has a ContextMenuStrip with 2 items. These are shown when right-clicking an UltraGridCell.
However, in order to show them, the user has to first click off the cell to take it out of edit mode, then right click on it to show the ContextMenuStripItems.
This has become confusing and irritating to the user, so I was wondering if there is any way that it can be changed to show them when right clicking whilst still in edit mode?
I've tried this to take it out of edit mode after a key is pressed, but it doesn't work.
Private Sub ugComm_keyup(sender As Object, e As KeyEventArgs) Handles ugComm.KeyUp
ugComm.UpdateData()
If ugComm.ActiveCell.IsInEditMode = True Then
ugComm.ActiveCell.Row.Update()
End If
End Sub
I also tried something in the MouseClick that was suggested on the Infragistics forums, but again it didn't work.
Is there any way that a user right-clicking a cell that is in edit mode can bring up the ContextMenuStripItems rather than this menu?
The above image shows what is currently show when right-clicking a cell in edit mode (The cell is the bottom right white cell). I don't want this to appear, but the CMS instead.
EDIT
I've tried the suggestions in the current answers, but neither of those worked for me. Possibly because the grids are a slightly older version?
My most recent effort was done with the following code:
Private Sub ugComm_MouseDown(sender As Object, e As MouseEventArgs) Handles ugComm.MouseDown
If e.Button = Windows.Forms.MouseButtons.Right Then
Me.cmCommRate.Show(mouseX, mouseY)
End If
End Sub
But this wasn't triggered until the cell was no longer in edit mode.
NEITHER OF THE ANSWERS BELOW RESOLVE THE ISSUE. STILL NEEDS AN ANSWER
When any cell of the grid enters in edit mode a TextBox is drawn over the cell. The nice part here is this text box is reused for all the cells in the grid. When you right click on the cell in edit mode the default context menu, that comes from MS, shows. What you need to do is get this text box and assign it your context menu strip. You can do this by handling ControlAdded event of the grid like this:
' create a field to store the TextBox
Private cellTextBox As TextBox
Private Sub grid_ControlAdded(sender As Object, e As ControlEventArgs) Handles grid.ControlAdded
' Check if added control is TextBox
If TypeOf e.Control Is TextBox Then
' If added control is TextBox store it in your private field and set its ContextMenuStrip
If Me.cellTextBox Is Nothing Then
Me.cellTextBox = DirectCast(e.Control, TextBox)
Me.cellTextBox.ContextMenuStrip = Me.ctx
End If
End If
End Sub
I have tried to write an event handler for the MouseUp event with this code
Private Sub grid_MouseUp(sender As Object, e as MouseEventArgs) Handles grid.KeyUp
grid.PerformAction(UltraGridAction.ExitEditMode)
grid.ContextMenuStrip.Show()
End Sub
and it works.
The ContextMenuStrip was added in code with this text (as example)
ContextMenuStrip ctx = new ContextMenuStrip()
ctx.Items.Add("Test1")
ctx.Items.Add("Test2")
ctx.Items.Add("Test3")
grid.ContextMenuStrip = ctx

How to change the cursor from One textbox to another

I have Two text Boxes named Text1,text2.Once I finished the value input into Text1 I would like to move the cursor automatically to Tex2.I don't like to put a maximum length for Text1,
The valued finished indication I would like in Text1 is Mouse click out of Text1.
Please help me to code it in vb.net
You need to set focus to the textbox2 on textbo1's lost focus event
Private Sub TextBox1_LostFocus(sender As Object, e As System.EventArgs) Handles TextBox1.LostFocus
TextBox2.Focus()
End Sub
or in other ways :
in form load put the code like this :
TextBox1.TabIndex = 0
TextBox2.TabIndex = 1
Reference:
GotFocus :Occurs when the control receives focus (occur when Cursor inside the textbox)
LostFocus :Occurs when the control loses focus(occur when Cursor leaves thetext box)
then simply you can redirect to the textbox2 from textbox1 by clicking the tab key

Vb.net Set focus to nested control on another open form

I have a form that I open from a menu item on my main form that has a datagridview that contains a control name. When I click on the control name I'd like it to set focus back to the main form and focus the control. I can get it to work if the control name is a control on the current tab, but if I try to focus to a control on another tab on my main form it does not focus. I don't get an error, it just doesn't focus.
Any assistance you could give me to point me in the right direction would be most appreciated. Thanks
My main form consists of nested controls:
Tabcontrol
Tabpage
Groupbox
Control (such as textbox, etc)
Here is my code from the 2nd form:
Public Property f1 As MainForm
Private Sub DataGridView1_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
For Each cont As Control In f1.Controls
For Each Tp As TabPage In cont.Controls
For Each gbx As GroupBox In Tp.Controls
For Each ctrl As Control In gbx.Controls
If ctrl.Name = DataGridView1.SelectedCells(1).Value Then
ctrl.Focus()
Exit For
End If
Next ctrl
Next gbx
Next Tp
Next cont
Me.Close()
end sub