I override ProcessCmdKey and when I get Keys argument, I want to check if this Keys is Letter or Digit or Special Symbol.
I have this snippet
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
char key = (char)keyData;
if(char.IsLetterOrDigit(key)
{
Console.WriteLine(key);
}
return base.ProcessCmdKey(ref msg, keyData);
}
Everything works for letters and digits. but when I press F1-F12 it converts them to letters.
Maybe someone knows better way to solve this task?
Override the form's OnKeyPress method instead. The KeyPressEventArgs provides a KeyChar property which allows you to utilize the static methods on char.
As mentioned by Cody Gray in the comments, this method only fires on key strokes that have character information. Other key strokes such as F1-F12 should be processed in OnKeyDown or OnKeyUp, depending on your situation.
From MSDN:
Key events occur in the following
order:
KeyDown
KeyPress
KeyUp
The KeyPress event is not raised by
noncharacter keys; however, the
noncharacter keys do raise the KeyDown
and KeyUp events.
Example
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (char.IsLetter(e.KeyChar))
{
// char is letter
}
else if (char.IsDigit(e.KeyChar))
{
// char is digit
}
else
{
// char is neither letter or digit.
// there are more methods you can use to determine the
// type of char, e.g. char.IsSymbol
}
}
Try
if( !(keyData >= Keys.F1 && keyData <= Keys.F12))
{
char key = (char)keyData;
if(char.IsLetterOrDigit(key))
{
Console.WriteLine(key);
return false;
}
}
return base.ProcessCmdKey(ref msg, keyData);
Try using keyData.KeyCode and maybe even testing within a range instead of using the Char.IsLetterOrDigit. e.g.
if (keyData.KeyCode >= Keys.D0 && keyData.KeyCode <= Keys.Z) {
...
}
you need either a giant switch/case statement or check for ranges. You may find it easier to check for the keys you want to exclude, depending on which there is fewer of. Look at this for all the possible values. http://msdn.microsoft.com/en-us/library/system.windows.forms.keys.aspx
if (keyData >= Keys.A && keyData <= Keys.Z)
// do something
or
switch(keyData) {
case Keys.Add:
case Keys.Multiply:
// etc.
// do something
break;
}
I have tried the following code but for some reason char.IsLetter() method is recognising the following keys as Letters???
F1, F8, F9, F11, F12, RightShift, LeftShift, RightAlt, RightCtrl, LeftCtrl, LeftWin, RightWin, NumLock.
This method doesn't seem to be that full proof regarding what it thinks is a letter.
if(char.IsLetter((char)e.Key) || char.IsDigit((char)e.Key))
if (keyData >= Keys.F1 && keyData <= Keys.F12)
{
//one of the key between F1~F12 is pressed
}
Related
For example, I have a string like:
ItemA MMC FG MMC 0802 EA 1 21175393
That has 5 tabs on it:
ItemA/tab/MMC FG/tab/MMC 0802/tab/EA/tab/1/tab/21175393
This string is received by a QR Code input being scanned from a tag, now, the problem here is that the input is being done within a cell in a DataGridView, so, when the first tab appears it'll change the selected column to the next one.
Setting the property "StandardTab" to False kinda works, but now when I input the QR Code string it stops the editing mode when the first tab appears.
I was trying to use
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(keyData == Keys.Tab && dGItems.EditingControl != null && msg.HWnd == dGItems.EditingControl.Handle
&& dGItems.SelectedCells.Cast<DataGridViewCell>().Any(x => x.ColumnIndex ==4))
{
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
And this helps, but it replaces the tabs from the scanned QR Code string with empty spaces and I don't want this to happen.
That has 5 tabs on it:
ItemAMMC FGMMC 0802EA121175393
How can I allow tab inputs in a cell without replacing them or ignoring them?
(This is because I need to catch the last tab in order to receive the number next to it)
Solved by:
First, creating two variables: a counter and a string.
int counter = 0;
string keyChar = "";
Next, creating a method to handle the occurrences of a tab key and counting them. When the tab keys repeat N times (in my particular case, 5 times) save the keyChar using KeysConverter.
public string CatchQRInput(Keys keyData)
{
KeysConverter kc = new KeysConverter();
if (keyData == Keys.Tab) counter++;
if(counter == 5)
{
keyChar += kc.ConvertToString(keyData);
}
// Replace the 5th Tab
keyChar = keyChar.Replace("Tab", "");
return keyChar;
}
Calling the said method into ProcessCmdKey:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
CatchQRInput(keyData);
if (keyData == Keys.Tab && dGItems.EditingControl != null && msg.HWnd == dGItems.EditingControl.Handle
&& dGItems.SelectedCells.Cast<DataGridViewCell>().Any(x => x.ColumnIndex ==4))
{
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
With this, the last value will be stored in the string keyChar, this is not the last thing to do, because you can clear the string in order to store multiple values, but for my particular case is enough.
I am in the process of creating a POS system using C# and I have an issue with Textbox to read bar-code.
I want to read bar-code from the scanner either when the textbox has focus or not. Again I want the textbox to have capability to search for product manually that is user input the bar-code and then press the enter key the bar code captured should be used to query MySQL.
I have used this code to read bar-code from scanner when my textbox has focus or not but the problem is that when I want to search for product manually using enter key the method to query db is getting invoked twice and I don't understand why. Need help to prevent the function from getting invoked twice as well as provide functionality to search bar-code on enter and when textbox has no focus that is get input from scanner
private string _barcode = "";
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)//read when no focus
{
char c = (char)keyData;
if (char.IsNumber(c))
_barcode += c;
if (c == (char)Keys.Return)
{
read_scanner(_barcode);
_barcode = "";
}
return base.ProcessCmdKey(ref msg, keyData);
}
This my code to search manually
private void txtbarcode_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// onQuery = true;
read_scanner(txtbarcode.Text);
}
}
And here is my method which is getting invoked twice when I press enter key
Product product;
public void read_scanner(string barcode)//this method is getting invoked twice when i search product manually
{
//
product = HibernateDao.getRecord("from Product u where u.barcode='"+barcoded+"'");
if (product != null)
{
pos_datagrid.Rows.Add(barcode, product.product_name, product.product_desc, null, "1", null, product_Cost);
}
else
{
AppUtil.showErrorBox("Invalid bar code!!");
}
}
The ProcessCmdKey is a virtual method on all Forms that listens to all keys and return true if it was a command key and false for other keys, so you might not need to implement KeyDown at all.
documentation here
I've changed the code a little to make use of a StringBuilder and add the values to that StringBuilder.
StringBuilder _barcodeBuilder = new StringBuilder();
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData != Keys.Return)
{
switch (keyData)
{
case Keys.NumPad0:
_barcodeBuilder.Append(0);
break;
case Keys.NumPad1:
_barcodeBuilder.Append(1);
break;
case Keys.NumPad2:
_barcodeBuilder.Append(2);
break;
case Keys.NumPad3:
_barcodeBuilder.Append(3);
break;
//and so on for the rest of the numpad keys
default:
_barcodeBuilder.Append((char)keyData);
break;
}
}
else
{
MessageBox.Show(this, _barcodeBuilder.ToString());
//read_scanner(_barcodeBuilder.ToString());
textBox1.Clear();
_barcodeBuilder = new StringBuilder();
}
return base.ProcessCmdKey(ref msg, keyData);
}
Numpad keys are a bit strange, so you can handle them with a switch statement.
The source of your problem is unclear. Although if you want to track the source of what triggers your method, use System.Environment.StackTrace and output that as a debug message. You might have to use the "Debug" configuration for that.
I'm making a custom Terminal in a C# winform. When the user presses a key in the TextBox that I'm using I have to make sure that it's a valid key. I need to prevent them from being able to delete stuff and do whatever they want. I managed to handle the backspace and delete and others via the KeyPress and KeyDown events. I had a problem with the user pressing shift + delete. It deletes stuff just like backspace. I don't know what the integer equivalent of it is. I made a C++ program to detect it, it was simple:
char c = _getch();
cout << (int)c << endl;
I got a -32. It didn't work in C#.
After so many tries to encircle its value, I found that it was 0.
It worked, at least for yesterday, but now it doesn't. I'm also able to delete stuff with the shift+delete.
Here's my key validation method:
private bool IsInvalidKey(char key)
{
bool condition1 = !IsAsciiKey(key) && !IsNavigatingKey(key); // by navigation I mean: left, right, end and home keys.
bool condition2 = (GetCaretPosition() == CaretPosition.OutsideCommandLine && !IsNavigatingKey(key));
bool condition3 = ((key == (char)Keys.Back) && GetCaretPosition() == CaretPosition.BeginningOfCommandLine);
return (condition1 || condition2 || condition3);
}
private bool IsAsciiKey(char key)
{
return ((int)key > 0 && (int)key <= 127); // char(0) should be shift+delete
}
How can I detect this key and where (in which event, KeyPress or KeyDown?)
I'm using a normal TextBox control, not a RichTextBox.
You could try something like this in the KeyDown event.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Shift && e.KeyCode == Keys.Delete) e.Handled = true;
}
Rather than trying to look at each individual key through the use of the KeyDown event, what you really need to do is do all of your validation in the TextChanged event, and you need to validate the entire entry (not just the last character) every time anything changes. This is the only way to support everything that the user could possibly do. As an example, the user could use the mouse to cut or paste text in the textbox, and that doesn't trigger any key press events at all.
If you want, you can handle the key press event as well so that you can prevent invalid characters/key from changing the text in the first place (and causing a full validation) but that's basically like performing client side validation of a field on a webpage; it's nice to do, but since you can get around it you can't only use it.
I'm trying to make use of the WindowsInputSimulator library to help me simulate keyPresses.
The software will consist of a client and a server. When a key is entered on the Client, it's KeyEventArgs are sent to the Server. The server then does the following with it:
public void SendKeyDown(Keys keyCode, Keys modifiers)
{
uint nonVK = MapVirtualKey((uint)keyCode, 2);
char mappedChar = Convert.ToChar(nonVK);
if (modifiers.Equals(Keys.None))
{
VirtualKeyCode vkc;
if (Enum.TryParse(VkKeyScan(mappedChar).ToString(), out vkc))
{
InputSimulator.SimulateKeyDown(vkc);
}
}
else
{
//Find out which modifier we're working with.
uint modVK = MapVirtualKey((uint)modifiers, 2);
char modifierChar = Convert.ToChar(modVK);
VirtualKeyCode vkc, modVkc;
if (Enum.TryParse(VkKeyScan(mappedChar).ToString(), out vkc)
&& Enum.TryParse(VkKeyScan(modifierChar).ToString(), out modVkc))
{
InputSimulator.SimulateModifiedKeyStroke(modVkc, vkc);
}
}
}
Which works for single keys. However, I'm trying to work with modifier keys as well, and I'm running in to some trouble. For example, pressing SHIFT + K produces "k2" Which leads me to believe either my transation into VirtualKeyCodes is wonky, or something else is.
Also, when sending these commands, should I catch only the KeyDown / KeyUp events? Or should I also watch for the KeyPress event? I should be able to wrok with arrow keys and non-Character keys as well, which makes me think I should just ignore the KeyPress.
EDIT: Also, how would I know when I'm working with multiple modifiers? How should I be stringing them together?
Thoughts? Thanks!
I was able to get it working with the following. Keep in mind this works for a SINGLE modifier, and a single CHARACTER. Special characters don't yet work with this code, but I figure it's a step in the right direction, and answered my immediate question.
public void SendKey(int keyValue, Keys modifiers)
{
VirtualKeyCode key;
if (modifiers.Equals(Keys.None))
{
if (Enum.TryParse(VkKeyScan(((char)keyValue)).ToString(), out key))
{
InputSimulator.SimulateKeyDown(key);
InputSimulator.SimulateKeyUp(key);
}
}
else if (modifiers.Equals(Keys.Shift) && keyValue >= (int)Keys.A && keyValue <= (int)Keys.Z)
{
if (Enum.TryParse(VkKeyScan(((char) keyValue)).ToString(), out key))
{
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.SHIFT, key);
}
}
else if (modifiers.Equals(Keys.Control) && keyValue >= (int)Keys.A && keyValue <= (int)Keys.Z)
{
if (Enum.TryParse(VkKeyScan(((char)keyValue)).ToString(), out key))
{
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, key);
}
}
else if (modifiers.Equals(Keys.Alt) && keyValue >= (int)Keys.A && keyValue <= (int)Keys.Z)
{
if (Enum.TryParse(VkKeyScan(((char)keyValue)).ToString(), out key))
{
//Alt is named MENU for legacy purposes.
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.MENU, key);
}
}
}
To keep myself interested, I try to put little Easter Eggs in my projects (mostly to amuse myself). I've seen some websites where you can type a series of letters "aswzaswz" and you get a "secret function" - how would I achieve this in C#?
I've assigned a "secret function" in the past by using modifier keys
bool showFunThing = (Control.ModifierKeys & Keys.Control) == Keys.Control;
but wanted to get a bit more secretive (without the modifier keys) I just wanted the form to detect a certain word typed without any input ... I've built a method that I think should do it:
private StringBuilder _pressedKeys = new StringBuilder();
protected override void OnKeyDown(KeyEventArgs e)
{
const string kWord = "fun";
char letter = (char)e.KeyValue;
if (!char.IsLetterOrDigit(letter))
{ return; }
_pressedKeys.Append(letter);
if (_pressedKeys.Length == kWord.Length)
{
if (_pressedKeys.ToString().ToLower() == kWord)
{
MessageBox.Show("Fun");
_pressedKeys.Clear();
}
}
base.OnKeyDown(e);
}
Now I need to wire it up but I can't figure out how I'm supposed to raise the event in the form designer ... I've tried this:
this.KeyDown +=new System.Windows.Forms.KeyEventHandler(OnKeyDown);
and a couple of variations on this but I'm missing something because it won't fire (or compile). It tells me that the OnKeyDown method is expecting a certain signature but I've got other methods like this where I haven't specified arguments.
I fear that I may have got myself confused so I am turning to SO for help ... anyone?
EDIT: The ProcessCmdKey seems to be the way that works with the following:
private StringBuilder _pressedKeys = new StringBuilder();
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const string kWord = "fun";
char letter = (char)keyData;
if (!char.IsLetterOrDigit(letter))
{return true;}
_pressedKeys.Append(letter);
if (_pressedKeys.Length == kWord.Length)
{
if (_pressedKeys.ToString().ToLower() == kWord)
{
MessageBox.Show("Fun");
_pressedKeys.Clear();
}
_pressedKeys.Clear();
}
return true;
}
Thanks all!
Try this:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.P|Keys.Control))
{
//do my prank
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
This will fire when you press CTRL + P.
refer: ProcessCmdKey
This method is called during message preprocessing to handle command
keys. Command keys are keys that always take precedence over regular
input keys. Examples of command keys include accelerators and menu
shortcuts. The method must return true to indicate that it has
processed the command key
You are overriding a virtual method, so you do not need to handle the KeyDown event. If you debug, you should hit a breakpoint in you overriden method if something calls the virtual method.
Are you sure you are overriding the correct method in the correct class though? Just a thought.