I have made a Windows Form application with a textbox which uses Barcode scanner to get any input value. I want user to use only Barcode Scanner to fill any value in it, and don't want to enter any input using my regular keyboard.
Since my Barcode works mimics as a keyboard, so disabling my regular keyboard will also disable my Barcode scanner to work.
I've searched manywhere to implement this, and found few answers were suggesting to add a Stopwatch/Timer to eliminiate all keypress which occurs within 50milliseconds, since Barcode can scan all values within 50 milliseconds, but no human can type faster than 50 miliseconds.
I also tried this way, but this fails when I randomly punches my fingers on keyboard keys, it reads out since some of keys fired within 50miliseconds.
Also tried below code but even this does not work as expected for me
private void rtBoxInput_KeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
}
Please suggest some good way to implement this?
The basic idea is to check:
if KeyUp and KeyDown events are fired of same keys and within specified time (say 17milliseconds), as this can be only done using Barcode scanner.
No one can trigger KeyDown and KeyUp event of same key within 17 milliseconds. For example it will take more than specified time for someone to Press and Release same key, however he can hit punch to keyboard that will push multiple keys all together and trigger their KeyDown and KeyUp events, but all no keys will have KeyUp and KeyDown events fired synchronously. So by this way you can detect whether input made by regular keyboard or barcode scanner.
Please have a look below:
public partial class BarcodeReader : Form
{
char cforKeyDown = '\0';
int _lastKeystroke = DateTime.Now.Millisecond;
List<char> _barcode = new List<char>(1);
bool UseKeyboard = false;
public BarcodeReader()
{
InitializeComponent();
}
private void BarcodeReader_Load(object sender, EventArgs e)
{
this.KeyDown += new KeyEventHandler(BarcodeReader_KeyDown);
this.KeyUp += new KeyEventHandler(BarcodeReader_KeyUp);
}
private void BarcodeReader_KeyUp(object sender, KeyEventArgs e)
{
// if keyboard input is allowed to read
if (UseKeyboard && e.KeyData != Keys.Enter)
{
MessageBox.Show(e.KeyData.ToString());
}
/* check if keydown and keyup is not different
* and keydown event is not fired again before the keyup event fired for the same key
* and keydown is not null
* Barcode never fired keydown event more than 1 time before the same key fired keyup event
* Barcode generally finishes all events (like keydown > keypress > keyup) of single key at a time, if two different keys are pressed then it is with keyboard
*/
if (cforKeyDown != (char)e.KeyCode || cforKeyDown == '\0')
{
cforKeyDown = '\0';
_barcode.Clear();
return;
}
// getting the time difference between 2 keys
int elapsed = (DateTime.Now.Millisecond - _lastKeystroke);
/*
* Barcode scanner usually takes less than 17 milliseconds as per my Barcode reader to read , increase this if neccessary of your barcode scanner is slower
* also assuming human can not type faster than 17 milliseconds
*/
if (elapsed > 17)
_barcode.Clear();
// Do not push in array if Enter/Return is pressed, since it is not any Character that need to be read
if (e.KeyCode != Keys.Return)
{
_barcode.Add((char)e.KeyData);
}
// Barcode scanner hits Enter/Return after reading barcode
if (e.KeyCode == Keys.Return && _barcode.Count > 0)
{
string BarCodeData = new String(_barcode.ToArray());
if (!UseKeyboard)
MessageBox.Show(String.Format("{0}", BarCodeData));
_barcode.Clear();
}
// update the last key press strock time
_lastKeystroke = DateTime.Now.Millisecond;
}
private void BarcodeReader_KeyDown(object sender, KeyEventArgs e)
{
//Debug.WriteLine("BarcodeReader_KeyDown : " + (char)e.KeyCode);
cforKeyDown = (char)e.KeyCode;
}
}
Check Here.. GitHub Link
If your barcode mimics a keyboard - there is no way you can find which one is inputing text in your TextBox. Can your barcode scaner add some prefix to scanned code? If yes - I think this is a best option in combination with 50ms timer.
What you can do is to handle your Barcode directly on your form using a KeyPress Event and disable your TextBox :
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
barcode = string.Empty;
try
{
barcode += e.KeyChar;
if (lastTime > new DateTime())
{
if (DateTime.Now.Subtract(lastTime).Milliseconds > 30)
{
f1 = false;
}
else
{
f1 = true;
}
}
lastTime = DateTime.Now;
/*
Test your Barcode, and if it matches your criteria then change your TextBox text
TextBox1.Text = barcode;
*/
}
catch (Exception ex)
{
MessageBox.Show("Something went wrong");
}
}
Don't forgot to set Form1.KeyPreview = true and it should do the trick !
Related
I've an application that changes the text of the label to a serial number that is scanned using a barcode scanner. The code works up until I have buttons on my form.
I've tried (1) focusing on the label, (2) creating a groupbox and putting the label in the groupbox and focusing on that, using both tab order and this:
this.ActiveControl = groupBox2;
And neither work.
Here is code outlining the the application:
private void Form1_Load(object sender, EventArgs e)
{
this.ActiveControl = groupBox2;
this.KeyDown += new KeyEventHandler(Form1_KeyDown);
this.KeyUp += new KeyEventHandler(Form1_KeyUp);
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
// if keyboard input is allowed to read
if (UseKeyboard && e.KeyData != Keys.Enter)
{
MessageBox.Show(e.KeyData.ToString());
}
/* check if keydown and keyup is not different
* and keydown event is not fired again before the keyup event fired for the same key
* and keydown is not null
* Barcode never fired keydown event more than 1 time before the same key fired keyup event
* Barcode generally finishes all events (like keydown > keypress > keyup) of single key at a time, if two different keys are pressed then it is with keyboard
*/
if (cforKeyDown != (char)e.KeyCode || cforKeyDown == '\0')
{
cforKeyDown = '\0';
_barcode.Clear();
return;
}
// getting the time difference between 2 keys
int elapsed = (DateTime.Now.Millisecond - _lastKeystroke);
/*
* Barcode scanner usually takes less than 17 milliseconds to read, increase this if neccessary of your barcode scanner is slower
* also assuming human can not type faster than 17 milliseconds
*/
if (elapsed > 17)
_barcode.Clear();
// Do not push in array if Enter/Return is pressed, since it is not any Character that need to be read
if (e.KeyCode != Keys.Return)
{
_barcode.Add((char)e.KeyData);
}
// Barcode scanner hits Enter/Return after reading barcode
if (e.KeyCode == Keys.Return && _barcode.Count > 0)
{
string BarCodeData = new String(_barcode.ToArray());
if (!UseKeyboard)
//MessageBox.Show(String.Format("{0}", BarCodeData));
label1.Text = String.Format("{0}", BarCodeData);
_barcode.Clear();
}
// update the last key press strock time
_lastKeystroke = DateTime.Now.Millisecond;
}
Again, it works as soon as I take the buttons out.
Here's a pic of my the UI:
Again, the label changes, until I start adding buttons to the WinForm.
Looking at the UI, the line that says, "Please Scan Serial..." should change when the user scans the barcode.
So what im looking to do is find if i have the space bar pressed at all and while it is i would like to have the space bar be released and then pressed again mutiple times with a delay of about 10 ms. i have tried to read and understand this link (https://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress.aspx) but it is still confusing any help? im brand new to c# but i have some experience with pascal of which i have found very similar
(using visual studio 2015 due to my computer not allowing me to update to windows 8.1)
10ms delay mean 100 times per second, no one could do it.
Key events occur in the following order:
KeyDown
KeyPress
KeyUp
Events KeyDown and KeyUp use KeyEventArgs, while KeyPress is KeyPressEventArgs,
KeyEventArgs could details how many keys are pressed at same time. KeyEventArgs.KeyCode is Keys which is a [Flags] enum, it could contains multiple keys, like CTRL+SHift+F+G
if your hotkey is Ctrl+Shift+Space, you can check with:
var hotkeyPressed = e.Control && e.Shift && e.KeyCode == Keys.Space;
if your hotkey is Ctrl+F10+Space, you can check with:
var hotkeyPressed = e.Control && e.KeyCode == (Keys.Space | Keys.F10);
but do not use:
var hotkeyPressed = e.Control && e.KeyCode.HasFlag(Keys.F10) && e.KeyCode.HasFlag(Keys.Space); // e.KeyCode probably contains other flags
KeyPressEventArgs.KeyChar is a string, take a look source code, focus on its comments
[ComVisible(true)]
public class KeyPressEventArgs : EventArgs
{
...
/// <summary>Gets or sets the character corresponding to the key pressed.</summary>
/// <returns>The ASCII character that is composed. For example, if the user presses SHIFT + K, this property returns an uppercase K.</returns>
public char KeyChar { get; set; }
...
}
to use which event, it depends on your requirement.
here is sample code in KeyDown:
private int counting = 0, limit = 10;
private void txt_KeyDown(object sender, KeyEventArgs e)
{
if (!e.KeyCode.HasFlag(Keys.Space)) //check if your expected key is pressed
{
counting = 0;
return;
}
//start counting
counting++;
if (counting > limit)
{
e.Handled = true;
//do you business work, like: Send something somewhere
}
else
{
//do something else, like: show the number 'counting' in GUI
}
}
if you want limit timespan with next space, use a Timer
private void txt_KeyDown(object sender, KeyEventArgs e)
{
timer1.Stop();
if (!e.KeyCode.HasFlag(Keys.Space))
{
counting = 0;
return;
}
//start counting
timer1.Start();
counting++;
if (counting > limit)
{
e.Handled = true;
//do you business work, like: Send something somewhere
}
else
{
//do something else, like: show the number 'counting' in GUI
}
}
//timer1.Interval = 100; //100ms timeout. user has to press space again within 100ms
private void timer1_Tick(object sender, EventArgs e)
{
counting = 0;
}
i want to ask, when iam using event keydown with counting the length of the text, it doesn't match. but when i press enter or backspace it become 9.
is there a way to make it count start from 1 instead of 0.
the code i use
private void textEdit1_KeyDown(object sender, KeyEventArgs e)
{
if (this.textEdit1.Text.Length == 10)
{
textEdit2.Text = textEdit1.Text;
this.textEdit1.Text = "";
}
label2.Text = textEdit1.Text.Length.ToString();
label1.Text = textEdit2.Text.Length.ToString();
}
You have to try the same in Key_Up event.
private void textEdit1_KeyUp(object sender, KeyEventArgs e)
{
if (this.textEdit1.Text.Length == 10)
{
textEdit2.Text = textEdit1.Text;
this.textEdit1.Text = "";
}
label2.Text = textEdit1.Text.Length.ToString();
label1.Text = textEdit2.Text.Length.ToString();
}
Because Key_Down will get executed as and when a key will be pressed and before you release the key.
And on other side Key_Up will get executed after you release the key on a keyboar so a typed character will be there in the textbox and you will get the desired result you want.
The problem is, that KeyDown-event is raised before Text-property is updated. If you need the length of the text after your key was processed you need to subscribe to another event, e.g. TextChanged.
I'm developing a program in Visual C# 2015 which should authenticate users through rfid cards. The device I'm using simply emulates a keyboard: let's say I open notepad, then swipe the tag or card near the reader, and I get the serial number + enter, much like most barcode readers work.
Obviously, I don't want the user to see the code, nor make him/her able to type it in a textbox, so the idea is catching the input from "that keyboard" at authentication, using KeyDown event, putting all characters in a buffer variable and then checking it against the database when enter is pressed (that is, the end of the code).
The problem is, say the card is marked as 12345678, this is what I get in notepad or in a textbox. But when I display the buffer, I get "D1D2D3D4D5D6D7D8"; I could simply avoid the problem by adding a D before each character of the database, but I really want to understand why this happens. Is it a matter of coding, or maybe the keydown events are too near to each other? Does anybody have a clue? Thank you
EDIT:
Here's the code:
XAML
<Window x:Class="myApp.MainWindow"
(...)
KeyDown="OnKeyDownHandler">
C#
private void OnKeyDownHandler(object sender, KeyEventArgs e)
{
if (!authenticated) {
if (e.Key != Key.Enter)
{
cardReadBuffer += e.Key;
}
else
{
//this returns every character preceded by a D; doesn't happen
//if I type some characters on my keyboard and then press enter
MessageBox.Show(cardReadBuffer);
cardReadBuffer = "";
}
}
}
The KeyDown event is just giving you the actual key being pressed, so try using the TextInput event to handle the string part:
private void OnKeyDownHandler(object sender, KeyEventArgs e) {
if (e.Key == Key.Enter) {
MessageBox.Show(cardReadBuffer);
cardReadBuffer = "";
e.Handled = true;
}
}
private void OnTextInput(object sender, TextCompositionEventArgs e) {
cardReadBuffer += e.Text;
}
I have a textbox and want user can not enter space in first textbox.the user can enter space in any where textbox apart of Beginning textbox.my computer = allow my computer = not allow (space in begining) , space maybe one or two or more.
If you really insist on doing this using one of the Events I would suggest you do it in the Text_Changed Event I have set you a simple way to do it..
private void txtaddgroup_TextChanged(object sender, EventArgs e)
{
var textBox = (TextBox)sender;
if (textBox.Text.StartsWith(" "))
{
MessageBox.Show("Can not have spaces in the First Position");
}
}
Implement a keypress event where you get rid of any spaces, read more here.
Add this bit of code to your KeyDown event handler to stop the space key ever being registered:
//Check to see if the first character is a space
if (UsernameTextBox.SelectionStart == 0) //This is the first character
{
//Now check to see if the key pressed is a space
if (e.KeyValue == 32)
{
//Stop the key registering
e.Handled = true;
e.SuppressKeyPress = true;
}
}
32 if the Key Code for the space character.
You should call this function with parameter as 'e' on KeyPress event:
Here 32 is the ASCII value of space
void SpaceValidation(KeyPressEventArgs e)
{
if (e.KeyChar == 32 && ActiveControl.Text.Length == 0)
e.Handled = true;
}
private void textbox1_KeyPress(object sender, KeyPressEventArgs e)
{
SpaceValidation(e);
}