I have a TabControl with several TabPages, each containing a series of PictureBox. I want to be able to navigate with the arrow keys inside those TabPages. I tried to give .Focus() to the TabPage when the user selects it, and then trap the PreviewKeyDown and KeyDown events, but it does not work. I've put a breakpoint at the PreviewKeyDown event handler, and it is not event reached.
Here is the activation of the TabPage :
Sub TilesetsTab_Selected(ByVal sender As Object, ByVal e As TabControlEventArgs) Handles TilesetsTab.Selected
Dim myTab As TabControl = CType(sender, TabControl)
If myTab.TabCount = 0 Then Exit Sub
Active.Tileset = Project.Tileset(CInt(myTab.SelectedTab.Tag))
Active.Tileset.Tab.Focus()
End Sub
And here is the Key event handlers
Sub Tab_KeyPreviewDown(ByVal sender As Object, ByVal e As PreviewKeyDownEventArgs) Handles Tab.PreviewKeyDown
If e.KeyCode = Keys.Left Or e.KeyCode = Keys.Right Or e.KeyCode = Keys.Up Or e.KeyCode = Keys.Down Then e.IsInputKey = True
End Sub
Sub Tab_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Tab.KeyDown 'BUG
Dim TilesWidth As Integer = Me.Tab.Width \ Me.ScreenSize
Select Case e.KeyCode
Case Keys.Left
If Active.Tile.Index = 0 Then Exit Sub
Me.Tile(Active.Tile.Index - 1).Selected()
Case Keys.Right
If Active.Tile.Index = Project.Tileset.Count - 1 Then Exit Sub
Me.Tile(Active.Tile.Index + 1).Selected()
Case Keys.Up
If Active.Tile.Index < TilesWidth Then Exit Sub
Me.Tile(Active.Tile.Index - TilesWidth).Selected()
Case Keys.Down
If Active.Tile.Index + TilesWidth > Active.Tileset.Count - 1 Then Exit Sub
Me.Tile(Active.Tile.Index + TilesWidth).Selected()
End Select
End Sub
Why can't I fire a KeyDown event on the TabPage ?
I don't know why the answer posted yesterday by someone (and the comments I made) were deleted, but it was said that TabPages could not have focus, and that it is restricted to TabControl. Following that advice, I shifted the PreviewKeyDown and KeyDown event handlers to TabControl events and it worked.
I'm losing some of the arrow navigation between TabPages, but it suits me.
Related
In Visual Basic, I try to move 2 Picture Boxes in my pong game using my keyboard ( 'W' and 'S' keys and up and down arrows).
They won't move if there are any buttons or text boxes on the screen, however they will when I remove the the button/text box. I think it might have to do with being able to use the arrow keys to navigate between them but I don't know how exactly to stop that from happening.
Using these events to move up, down,
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
Select Case e.KeyCode
Case Keys.Up
moveUp()
e.Handled = True
Case Keys.Down
moveDown()
e.Handled = True
End Select
End Sub
Private Sub Form1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs)
Select Case e.KeyCode
Case Keys.Up
moveUp()
Case Keys.Down
moveDown()
End Select
End Sub
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp
Select Case e.KeyCode
Case Keys.Up, Keys.Down
stopMoving()
e.Handled = True
End Select
End Sub
Private Sub moveUp()
Me.Text = "Moving Up"
End Sub
Private Sub moveDown()
Me.Text = "Moving Down"
End Sub
Private Sub stopMoving()
Me.Text = "Idle"
End Sub
you can also use the same events to handle up, down on the TextBoxes and Buttons. Add the handlers programmatically
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each c As Control In Me.Controls
AddHandler c.KeyDown, AddressOf Form1_KeyDown
AddHandler c.PreviewKeyDown, AddressOf Form1_PreviewKeyDown
AddHandler c.KeyUp, AddressOf Form1_KeyUp
Next
End Sub
Note: it will only add the handlers to controls directly on your form, not controls inside containers. Though, you can use an extension method to get all children, no matter how buried in containers. See https://stackoverflow.com/a/21388034/832052
in the form, i need check the textbox detail,so i use the Validated method.i also have a button to save form detail.and the button bind F10.
the text box Validated method
Private Sub txtReportCD_Validated(sender As Object, e As EventArgs) Handles txtReportCD.Validated
If txtReportCD.Text <> String.Empty Then
cboReportName.Value = txtReportCD.Text.Trim
Else
CommonMsg.showMsg("the CD not be empty")
End If
End Sub
the form keydown
Private Sub form_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If e.Alt AndAlso e.Control AndAlso e.Shift Then
Exit Sub
End If
Select Case e.KeyCode
'save data
Case Keys.F10
ClickButton(Me.btnSaveData, e)
e.Handled = True
End Select
End Sub
the ClickButton method
Private Sub ClickButton(ByVal btn As ButtonKdcCtrl, e As KeyEventArgs)
e.Handled = True
If e.Alt OrElse e.Control OrElse e.Shift Then
Exit Sub
End If
If btn.Enabled Then
btn.PerformClick()
End If
End Sub
the btnSaveData method
Private Sub btnSaveData_Click(sender As Object, e As EventArgs) Handles btnSaveData.Click
CommonMsg.showMsg("begin save data")
'do save form data
End Sub
when focus in txtReportCD,and i press F10 key. the form first do [btn.PerformClick], then do [txtReportCD_Validated] twice,last do [btnSaveData_Click].
but when focus in txtReportCD,and i click btnSavaData button.
the form first do [txtReportCD_Validated] once and not do [btnSaveData_Click].
how can i do,make when i press F10,the form do [txtReportCD_Validated] once
and the [btnSaveData_Click] not be call
PS: the txtReportCD text always empty.
I have a Form with a Panel containig 5 RadioButton
I've only handled the Click event of all RadioButtons.
When I use arrow keys to move from a RadioButton to another, the Click event is raised at each move.
Is it possible to only Select the RadioButton and Click it using SpaceBar?
I would you use the Form.KeyDown event of the parent form and do something like this:
Private Sub Form1_KeyPress(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
REM Check if space is the button pressed
If e.KeyCode = Keys.Space Then
REM See if a Radio Button has focus to know which was selected
If RadioButton1.ContainsFocus Then
RunMyCode(RadioButton1)
ElseIf RadioButton2.ContainsFocus Then
RunMyCode(RadioButton2)
End If
End If
End Sub
''' <summary>
''' Method which executes the code you want run when a radio button is selected
''' </summary>
''' <param name="rdButtona"></param>
Private Sub RunMyCode(ByRef rdButtona As RadioButton)
REM Check which radio button was selected and execute the apprpriate code
If rdButtona.Equals(RadioButton1) Then
MsgBox("Radio Button 1")
ElseIf rdButtona.Equals(RadioButton2) Then
MsgBox("Radio Button 2")
End If
End Sub
To prevent the RadioButton from being checked, handle the RadioButton.Click event and uncheck the RadioButton using radioButton1.checked = false. If you handle the RadioButton.CheckChanged event, radioButton1.checked = false will raise another CheckChanged event which we don't need. I would also do something there to show which radio button has been selected. In My example I change the text color but you can do whatever you want.
Private Sub RadioButton2_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton2.CheckedChanged
RadioButton2.Checked = False
ResetColors()
RadioButton2.ForeColor = Color.DarkRed
End Sub
Private Sub RadioButton3_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton3.CheckedChanged
RadioButton3.Checked = False
ResetColors()
RadioButton3.ForeColor = Color.DarkRed
End Sub
Private Sub RadioButton1_CheckedChanged(sender As Object, e As EventArgs) Handles RadioButton1.CheckedChanged
RadioButton1.Checked = False
ResetColors()
RadioButton1.ForeColor = Color.DarkRed
End Sub
Private Sub ResetColors()
RadioButton2.ForeColor = Color.Black
RadioButton1.ForeColor = Color.Black
RadioButton3.ForeColor = Color.Black
End Sub
Of course the code could be simplified, but this is the general idea.
The following code runs RadioButtons Click Event only on mouse click (or on spacebar press) and not on arrow keys press.
It also gives focus to RadioButton selected with Arrow Key
Dim HandleRBtnClick As Boolean = True
Private Sub RadioButtons_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles RadioButton1.Click, RadioButton2.Click, RadioButton3.Click, RadioButton4.Click
If Not HandleRBtnClick Then
With CType(sender, RadioButton)
.Checked = False
.Focus()
End With
Exit Sub
End If
'Code for RadioButton Checked (on mouse click or spacebar pressed)
Me.TextBox1.Text = CType(sender, RadioButton).Name
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If keyData = Keys.Left OrElse
keyData = Keys.Right OrElse
keyData = Keys.Up OrElse
keyData = Keys.Down Then
HandleRBtnClick = False
Else
HandleRBtnClick = True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
I Want to say sorry if there was a same question like i had. I have tried to Search but i couldn't find it, so.. i hope there is no other question like this..
To the point, i need your help to tell me how to change the Location of an object in a form
What i want to do is making the Button1 move to the left when i press the left key on the keyboard. But i have a problem with how to set the location (x,y) of the object
Private Sub Button1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Button1.KeyPress
If Asc(e.KeyChar) = Keys.Left Then
End If
End Sub
Thanks ...
By default, the arrow keys are not captured by the control's KeyPress, KeyDown or KeyUp events. You can make them be captured by KeyDown and KeyUp by setting e.IsInputKey to True in the PreviewKeyDown event. Then you can move the button sideways by changing its Left property. The following assumes the button has focus.
Private Sub Button1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) _
Handles Button1.PreviewKeyDown
If e.KeyCode = Keys.Left Or e.KeyCode = Keys.Right Then e.IsInputKey = True
End Sub
Private Sub Button1_KeyDown(sender As Object, e As KeyEventArgs) _
Handles Button1.KeyDown
Dim myButton As Button = CType(sender, Button)
If e.KeyCode = Keys.Left Then myButton.Left -= 1
If e.KeyCode = Keys.Right Then myButton.Left += 1
End Sub
Updated Solution
Here's a way to accomplish it so that it moves while holding down the key. Create a project with a Form and Button.
Right-click on the Project in the Solution Explorer and add two .NET References:
PresentationCore
WindowsBase
Here's the code. A timer will capture key events and move the button:
Imports System.Windows.Input
Public Class Form1
Private timex As New Timer
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
AddHandler timex.Tick, AddressOf myTickEvent
timex.Enabled = True
timex.Interval = 100
End Sub
Private Sub myTickEvent(sender As Object, e As EventArgs)
If isKeyPressed(Key.Left) Then
Me.Button1.Left -= 10
End If
If isKeyPressed(Key.Right) Then
Me.Button1.Left += 10
End If
If isKeyPressed(Key.Up) Then
Me.Button1.Top -= 10
End If
If isKeyPressed(Key.Down) Then
Me.Button1.Top += 10
End If
End Sub
Private Function isKeyPressed(ByRef keys As System.Windows.Input.Key)
If (Windows.Input.Keyboard.GetKeyStates(keys) And Windows.Input.KeyStates.Down) > 0 Then
Return True
Else
Return False
End If
End Function
End Class
Private Sub AccountType_KeyDOWN(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If e.KeyCode = Keys.Return Then
ProcessTabKey(True)
End If
End Sub
Private Sub anytextbox_Enter(sender As Object, e As EventArgs) Handles Twitter.Enter, Email.Enter, PhoneNoOffice.Enter, PhoneNoHome.Enter, PhoneNoMobile.Enter, EName.Enter, AName.Enter, IDCode.Enter, ExpiryDate.Enter, BankAccount.Enter
Dim txt As TextBox = DirectCast(sender, TextBox)
stroldvalue = txt.Text
End Sub
Private Sub anytextbox_KeyDown(sender As Object, e As KeyEventArgs) Handles Twitter.KeyDown, Email.KeyDown, PhoneNoOffice.KeyDown, PhoneNoHome.KeyDown, PhoneNoMobile.KeyDown, EName.KeyDown, AName.KeyDown, IDCode.KeyDown, ExpiryDate.KeyDown, BankAccount.KeyDown
Dim txt As TextBox = DirectCast(sender, TextBox)
If e.KeyCode = Keys.Enter Or e.KeyCode = Keys.Tab Then
If txt.Text <> stroldvalue Then
connectunauth()
cmd = New SqlCommand("Insert into changes values(#id,#txtname,#oldval,#newval)", Variables.UnauthCon)
cmd.Parameters.AddWithValue("#id", CustomerNo.Text)
cmd.Parameters.AddWithValue("#txtname", txt.Name)
cmd.Parameters.AddWithValue("#oldval", stroldvalue)
cmd.Parameters.AddWithValue("#newval", txt.Text)
cmd.ExecuteNonQuery()
UnauthCon.Dispose()
NOCHANGE = True
End If
End If
End Sub
In the above code i face the following error:
On entry into one textbox, the value is saved in stroldvalue.
On pressing enter after changing in the above, the form_keydown event triggers first, which runs the anytextbox_enter event causing the stroldvalue to be overwritten by the next textbox value. and then the textbox keydown event triggers.
I tried keypress event for the form, but keypress event does not capture enter key press on combobox.
What should i do so that the keydown of form triggers after textbox keydown event.