VB.net Key Combinations doesn't work - vb.net

The following code works for Ctrl + D, F2, and F7, but does not work for Ctrl + A. Anyone know what the issue could be?
Private Sub AgentSetupForm_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Select Case e.KeyCode
' Ctrl + A
Case Keys.A And (e.Control And Not e.Shift And Not e.Alt)
Dim f As New InvestorAccountsForm
f.MdiParent = TraderoomMDI
f.Show()
' Ctrl + D
Case Keys.D And (e.Control And Not e.Shift And Not e.Alt)
Dim f As New InvestorAddressForm
f.MdiParent = TraderoomMDI
f.Show()
' F2, F7
Case Keys.F2 'And (e.Shift And Not e.Control And Not e.Alt)
Me.Text = "F2 Test"
Case Keys.F7
stlFormMode.Text = "Edit"
End Select
End Sub

The accepted answer is totally incorrect.
VB.NET is not C#. So if And is used in a context with Booleans (on the both sides) VB.NET automatically switches to logical And as opposed to bitwise And. So this is not a problem at all. I just run the OP code and it ran fine - Ctrl + A combination was captured successfully. Furthermore, if a key combination means something for the OS (or some other component) it doesn't mean it won't be captured in our application.
The difference between And and AndAlso is that the first evaluates the Boolean expressions from left to right all along to the end, even though some of the expressions evaluates to False. The later evaluates expressions UNTIL it reaches False or to the end - that is short-circuiting.
To improve the readability of your code you can test for a particular key at the Case statement. Then insert an If block within the particular case to check the condition of control keys:
Select Case e.KeyCode
Case Keys.A
If e.Control AndAlso Not (e.Shift OrElse e.Alt)
Dim f As New InvestorAccountsForm
f.MdiParent = TraderoomMDI
f.Show()
End If
'
'
End Select
Or you can factor out the If block to embrace the Select Case for all the cases concerning the condition e.Control AndAlso ....
Unfortunately I cannot answer your question as it seems your issue cannot be (easily) reproduced. Based on the comments, it is more likely to be hardware or driver related problem than the Case statements in your code.

EDIT:
As it seems you have an issue with the CTRL + A combination, you could try overriding ProcessCmdKey and see if that works. The method should be called before the keys are handled and/or translated by the .NET environment.
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, keyData As System.Windows.Forms.Keys) As Boolean
If keyData = (Keys.Control Or Keys.A) Then
...your code here...
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
If the other combinations work you can keep them in the KeyDown event.
EDIT 2:
#BozhidarStoinev is right about what he says; I was wrong saying that you're currently using the bitwise And.
Apparently it works using And or AndAlso in Select Case-statements due to how boolean values are converted in VB.NET. In this case as long as the first operator is just And you'll be fine. The following AndAlsos below are used because they perform shortcircuiting, which is faster due to that AndAlso only evaluates the right side if the left side is True.
The following:
Keys.A And (e.Control AndAlso Not e.Shift AndAlso Not e.Alt)
converts to either:
(65 And True) = (65 And -1) = 65 'I added parentheses for improved readability
or:
(65 And False) = (65 And 0) = 0
It is not certain that multi-statement cases will work every time however. It might work for keys, but as <anything> And False equals to zero there is a chance for unexpected results if you are checking for 0 in another Case.

I know this question is old
But it works easily
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
Select Case keyData
Case (Keys.Control + Keys.Shift + Keys.Alt + Keys.B)
MsgBox("Control + Shift + Alt + B")
Return True
Case Keys.Control + Keys.Alt + Keys.C
MsgBox("Control + Alt + C")
Return True
End Select
Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Related

how to handle multiple KeyPress events

I need my win form - vb.net, to detect if Control + P is being pressed as well as Control + Shift + P as well as just the letter P being pressed.
i have ready how this should be done, and then wrote it into my application, however i can't get it to work so i assume im doing something fundamentally wrong.
my code
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyUp, MyBase.KeyDown
If e.KeyCode = Keys.F9 Then
System.Diagnostics.Process.Start("calc.exe")
End If
If e.KeyCode = (Keys.P AndAlso Keys.ControlKey AndAlso Keys.ShiftKey) Then
If PrintBatchStickersToolStripMenuItem.Enabled = False Then Exit Sub
If DataGridView1.Rows.Count = 0 Then Exit Sub
Dim rowIndex As Integer = 0
rowIndex = DataGridView1.CurrentRow.Index
PrintAllMatchingProductCodeToolStripMenuItem_Click(sender, e)
ElseIf e.KeyCode = (Keys.P AndAlso Keys.ControlKey) Then
If PrintBatchStickersToolStripMenuItem.Enabled = False Then Exit Sub
If DataGridView1.Rows.Count = 0 Then Exit Sub
Dim rowIndex As Integer = 0
rowIndex = DataGridView1.CurrentRow.Index
PrintBatchQTYToolStripMenuItem_Click(sender, e)
ElseIf e.KeyCode = Keys.P Then
If PrintBatchStickersToolStripMenuItem.Enabled = False Then Exit Sub
If DataGridView1.Rows.Count = 0 Then Exit Sub
Dim rowIndex As Integer = 0
rowIndex = DataGridView1.CurrentRow.Index
PrintSingleStickerToolStripMenuItem_Click(sender, e)
End If
End Sub
if i remove the brackets i can get it to detect the P key being pressed, but never the Control and the Shift or a combination of them two.
i added this to the KeyUp event as from my testing if i did this on keydown, and a user held down the keys, the code would loop over and over printing multiple copies of the sticker. and i need the code to only execute once.
keypress from my understanding wont handle the control and shift keys from what i could understand.
am i going wrong with the keyup, because the keys could be getting released at separate times? and if i cant use keyup how to do i handle not printing multiple times on keydown?
You need to use KeyData rather than KeyCode and you need to combine your Keys values properly:
Select Case e.KeyData
Case Key.P
'P was pressed without modifiers.
Case Keys.Control Or Key.P
'Ctrl+P was pressed without other modifiers.
Case Keys.Control Or Keys.Shift Or Keys.P
'Ctrl+Shift+P was pressed without other modifiers.
End Select
It may seem odd to use Or rather than And but this is a bitwise operation, not a Boolean operation. If you understand how bitwise logic works, which you should, then it's obvious why Or is used.
As an alternative:
If e.KeyCode = Keys.P AndAlso Not e.Alt Then
If e.Control Then
If e.Shift Then
'Ctrl+Shift+P was pressed without other modifiers.
Else
'Ctrl+P was pressed without other modifiers.
End If
Else
'P was pressed without modifiers.
End If
End If

Visual Studio ComboBox won't cycle through items with up/down arrows once users types

I have a userform with a dropdown combobox that is filled with items when the form is opened. If the box has focus, the up/down arrow keys will cycle through the items (as it should), or the user can select from the drop down list and still be able to use the up/down arrows from there. If the user starts typing, the box is set to append from the list items, but that disables the up/down arrow keys from cycling through ALL the items. At that point, it only cycles through the items that start with whatever the user typed. I would like it to erase the typed data and cycle through all the combobox items (starting at the index was whatever was appended) just like it does in the VBA version.
Even if the user types something, then selects a completely different item from the dropdown, the next time up/down keys are pressed, it only goes back to whatever was typed.
I attempted to handle this in the arrow up/down keydown (or keyup) event as follows:
Private Sub SeriesBox_KeyDown(sender As Object, e As KeyEventArgs) Handles SeriesBox.KeyDown
Dim CurIndex As Integer = SeriesBox.FindStringExact(SeriesBox.Text)
Select Case e.KeyCode
Case Keys.Down
SeriesBox.Text = String.Empty
SeriesBox.SelectedIndex = CurIndex + 1
Case Keys.Up
SeriesBox.Text = String.Empty
SeriesBox.SelectedIndex = CurIndex - 1
End Select
End Sub
The arrow keys don't actually enter this sub, so I tried adding:
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keydata As Keys) As Boolean
If keydata = Keys.Right Or keydata = Keys.Left Or keydata = Keys.Up Or keydata = Keys.Down Then
OnKeyDown(New KeyEventArgs(keydata))
ProcessCmdKey = True
Else
ProcessCmdKey = MyBase.ProcessCmdKey(msg, keydata)
End If
End Function
But this didn't seem to make a difference. Is there something I am missing?
This may work:
First set you combobox's AutoCompleteMode and AutoCompleteSouce to None
Then paste this to your code:
Private Sub SeriesBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles SeriesBox.TextChanged
For Each it As String In SeriesBox.Items
If Not SeriesBox.Text = it Then
If it.Contains(SeriesBox.Text) Then
Dim length As Integer = SeriesBox.Text.Length
SeriesBox.Text = ""
SeriesBox.Text = it
SeriesBox.Select(length, SeriesBox.Text.Length - length)
SeriesBox.SelectedItem = SeriesBox.Text
End If
End If
Next
End Sub

I want a combination of 1,0 like 110,101,100,001,010,000 on my text box. If somebody types 140, there is an error. How can I write to proceed this?

If (String.IsNullOrEmpty(bc.Text)) Then
MsgBox("Please Insert something into the text box.")
ElseIf Not Integer.TryParse(bc.Text, value) Then
MsgBox("Please Insert number into the B.C text box")
These are my error checking codes to notify people who have typed string or numbers other than integers. In the bc.Text, I only want 3 length combination of 0 and 1 like 100,101,110, etc. If somebody types 150, I want msg box to say "Please insert an appropriate number into B.C box". How can I proceed this? Thank you for your time!
You can use a Regular Expression, like this:
Imports System.Text.RegularExpressions
...
Dim rg As Regex = New Regex("^[01]{3}$")
Dim test As String = "111"
Dim b as Boolean = rg.IsMatch(test)
b will only be true if it matches any combinations of 3 1/0
Cheers
You can filter out your keypresses in the Textbox's KeyDown event using SuppressKeyPress to keep wrong value from showing in the Textbox.
This is a quick test of the concept:
Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown
If Not (e.KeyData = Keys.D1 Or e.KeyData = Keys.NumPad1 _
Or e.KeyData = Keys.NumPad0 Or e.KeyData = Keys.D0 _
Or e.KeyData = Keys.Back Or e.KeyData = Keys.Enter _
Or e.KeyData = Keys.Delete) Then
Beep()
e.SuppressKeyPress = True
End If
End Sub
A more primitive and probably performance inferior approach would be to first check the length and then use a string replace command to remove all "1" and "0" characters from the string, raising the message box if the resulting stripped string weren't empty.

How to prevent special characters in datagridview using vb.net

I have a windows forms vb.net program that uses a datagridview. I'm trying to find a way to prevent a user from entering special characters (e.g. $,#,!,#,%,^,&) in my datagridview. When the user inputs a special character I have an approprioate message box appear explaining their mistake, then I provide them a default value. I have everything working except a way to prevent the special character or symbols. I'm thinking something like this has to work, but I can't seem to find any way of preventing this sort of entry:
If (columnindex = 0) Then 'checking value for column 1 only
Dim cellString = DataGridView1.Rows(rowindex).Cells(columnindex).value
If cellString String.IsSymbol(cellString) = true Then
MessageBox.Show("Special Characters Not Allowed")
End If
DataGridView1.Rows(rowindex).Cells(columnindex).value = "Default Value"
Exit Sub
End If
You can use the EditingControlShowing event to register a KeyPress function for the input box.
Private Sub YourDataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles YourDataGridView.EditingControlShowing
Try
RemoveHandler e.Control.KeyPress, AddressOf YourFunctionToPreventSpecialCharacters
Catch ex As Exception
End Try
If Me.dgvTableViewer.CurrentCell.ColumnIndex = YourDataGridView.Columns("YourColumn").Index Then
AddHandler e.Control.KeyPress, AddressOf YourFunctionToPreventSpecialCharacters
End If
End Sub
Try and Put this in the DataGridView's keydown event:
Private Sub DataGridView1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown
Select Case e.KeyCode
Case Keys.D0 To Keys.D9 And e.Shift
MsgBox("NOPE.")
e.SuppressKeyPress = True
End Select
End Sub
That basically checks if the keypress is coming from the 0-9 keys on your computer and also if you are holding the SHIFT Key. If it is then it displays a Msgbox and Suppresses the keypress. This blocks chars on your keyboard's 0-9 shift !##$%^&*(). You can edit this like
Case Keys.A
e.Suppress ...
Msgbox ... etc

If else inside a loop in VB.Net

The code below shows the event when a button click is fire
Protected Sub btnFinish_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnFinish.Click
For i As Integer = 0 To Gridview1.Rows.Count - 1 Step i + 1
Dim TextBox1 As TextBox = DirectCast(Me.Gridview1.Rows(i).FindControl("txtAnswer"), TextBox)
If TextBox1.Text = String.Empty Then
'do something
ElseIf TexBox1 <> String.Empty Then
'do something else
End If
Next
End Sub
The problem here is that the only condition being executed is in the If-statement even if it should execute the ElseIf-statement. Can someone explain why and how can I solve this problem? [EDITED]
a couple of things to note when comparing text/string:
String could be NULL, instead of Empty
use String.IsNULLOrEmpty to check NULL/Empty
String could be WhiteSpace too, use String.IsWhiteSpace to check it
User could enter a few spaces in some cases, if you want to make sure it's correct, use String.Trim to eliminate any unwanted spaces.
normally what I do is: (NOT String.IsNULLOrEmpty(givenText)) AndAlso givenText.Trim.Length <> 0