Barcode scanner with a WPF application - c#

I have a barcode scanner (bluetooth) connected to my computer to use for scanning some barcodes. The scanner acts exactly like a keyboard does and returns whatever it scans. In my WPF application I have some textboxes for the user to manually enter in a product number, revision number, bin number, and lot number.
I would like the user to be able to instead scan the QR/Bar? code which has all that information in it at any time. So I have a few issues:
Is it possible to scan a barcode with your focus on anything in the app and NOT write it out like a keyboard? Example, I have a random textbox highlighted right now but I go and scan a code - I dont want the code to fill in this random textbox - I would want something like all the scanned text goes into a variable.
If step 1 is not possible. The way I currently have it set up is you need to click into a specific textbox. Which on TextChanged will parse it and try to figure out where the pieces need to go. But it will trigger when each character is added to the box. I have about ~30 characters per code so this will slow it down tremendously. I tried to see what other event might work but I don't see any other solution to that issue? Is there some other event that I'm just missing?
Thank you

I dont want the barcode to fill random textboxes - I want all the scanned QR/barcode into a variable.
private string barCode = string.Empty; //TO DO use a StringBuilder instead
private void Window_Loaded(System.Object sender, System.Windows.RoutedEventArgs e)
{
MainWindow.PreviewKeyDown += labelBarCode_PreviewKeyDown;
}
private void labelBarCode_PreviewKeyDown(object sender, KeyEventArgs e)
{
if ((44 == e.Key)) e.Handled = true;
barCode += e.Key;
//look for a terminator char (different barcode scanners output different
//control characters like tab and line feeds), a barcode char length and other criteria
//like human typing speed &/or a lookup to confirm the scanned input is a barcode, eg.
if (barCode.Length == 7) {
var foundItem = DoLookUp(barCode);
barCode = string.Empty;
}
}
See update, as at March 2019:
https://stackoverflow.com/a/55411255/495455

Related

C# Masked textbox with date format skips first character

I have a problem in a winform app.
I have several masked textbox which use the short date mask (//____), the problem is that if I select all the text (either with Ctrl + a or from code) and I write a new date is like that the first character goes at an 11th position (the mask disappear and i see only the character I wrote) and if I press backspace the text becomes something like this _1/01/1979 and I have to select all again and press backspace or delete everything.
I handled in this way
private void maskedTxt_KeyPress(object sender, KeyPressEventArgs e)
{
MaskedTextBox msk = sender as MaskedTextBox;
if (msk != null)
{
if (!string.IsNullOrEmpty(msk.Text.Replace("/", string.Empty).Replace(":", string.Empty).Trim()) && _focused)
{
_focused = false;
SendKeys.SendWait("{BACKSPACE}");
}
}
}
_focused is a Boolean variable that I set to true if a validation error happens at the leave event of the masked textbox (invalid date, the date is too big or too small etc...)
so that when someone enters the textbox the text can be written correctly
Is there a better way to handle this "error" or this is good? I tried it and it worked but a lot of people will have to use this application and probably there will be some errors along the way.
Thanks

How can I copy a line from a Richtextbox when I select it?

I am trying to automatically highlight and copy a single line from a rich text box and store it in a variable when I click on any part of the line.
Is this possible?
The Click event and something like the following should help:
private void richTextBox1_Click(object sender, EventArgs e)
{
int index = richTextBox1.SelectionStart;
int line = richTextBox1.GetLineFromCharIndex(index);
string lineText = (richTextBox1.Lines.Length > 0) ? richTextBox1.Lines[line] : "";
//Debug output for my own testing purposes
Debug.WriteLine(lineText);
}
You may want to do something different when the RichTextBox is empty. I just use an empty string.
Here's an example of the output from a simple app:
The text show in the output window reflects the order in which I clicked the lines after typing.
However, one caveat to this is that you don't need to click exactly on the line for it to count. For example, clicking in the empty space below the last line registers as clicking the last line, because that's where the cursor ends up. It might not matter a whole lot, but it's something to be aware of.

Second TextBox showing same Text Selection as first

Long time listener, first time caller here. I'm having a strange issue with the TextBox in WinRT C#/XAML that I hope someone may be able to help me with.
Basically, I'm working on creating a Custom Control that essentially requires a second TextBox to be a copy of the first, including showing the same Text, and showing the same Selected Text. Obviously for the Text requirement I simply respond to the TextChanged event on the first TextBox and set the Text of the second TextBox to the Text from the first, which works great.
For the Selected Text requirement I started with a similar solution, and my code for this is as follows:
void TextBox1_SelectionChanged(object sender, RoutedEventArgs e)
{
this.TextBox2.Select(this.TextBox1.SelectionStart, this.TextBox1.SelectionLength);
}
This seemed to work pretty well when initially used with a mouse:
But I'm having a problem when selecting text with Touch. I double-tap within the TextBox to create the first "anchor" as you do in Touch, then drag to begin the selection; but I only ever manage to select a single character normally before the selection stops. The TextBox doesn't lose focus exactly, but the behaviour is similar to that; the selection anchors disappear and I can't continue selecting anything unless I re-double-tap to start a new selection. If I remove the code to select text in TextBox2 then the Touch selection behaves perfectly in TextBox1.
I've been trying to fix this for a while and cannot, I'm not sure if I can get the desired behaviour with WinRT TextBoxes. Does anyone have any ideas? Or perhaps another way to implement a solution with two TextBoxes with this behaviour?
Thanks a lot.
So this is far from an answer, but discovered a few things that maybe will help you or others come up with a potential workaround. Apologies if these are things you've already seen and noted.
First, it's not the call to TextBox2.Select() that's the problem per se. This for instance, works fine for me
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
TextBox2.Select(3, 5);
}
unfortunately, using start and length versus the hard-coded 3 and 5, that is, the following, DOES NOT WORK:
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
TextBox2.Select(start, length);
}
I also discovered that I could select TWO characters if I started from the end, but only one from the beginning. That got me to thinking about dispatching the call to set the second selection:
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low,
() => TextBox2.Select(start, length));
}
Now I can select 2 from the front and 3 and sometimes 4 from the back. Took it a step further, and was able to select as many as six or seven with a really fast swipe.
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
Dispatcher.RunIdleAsync((v) => Highlight());
}
public void Highlight()
{
TextBox2.Select(TextBox1.SelectionStart, TextBox1.SelectionLength);
}
Seems like the trick to working around this is not setting TextBox2 until whatever vestiges of the TextBox1 SelectionChanged event have completed.
This may be worth registering on Connect.
Mine is only a partial solution as well.
I did some debugging and noticed that the SelectionChanged event is fired throughout the text selection process. In other words, a single finger "swipe" will generate multiple SelectionChanged events.
As you found out, calling TextBox.Select during a text selection gesture affects the gesture itself. Windows seems to stop the gesture after the programmatic text selection.
My workaround is to delay as long as possible calling the TextBox.Select method. This does work well, except for one edge case. Where this method fails is in the following scenario:
The user begins a select gesture, say selecting x characters. The user, without taking their finger off the screen, pauses for a second or two. The user then attempts to select more characters.
My solution does not handle the last bit in the above paragraph. The touch selection after the pause does not actually select anything because my code will have called the TextBox.Select method.
Here is the actual code. As I mentioned above, there are multiple selection changed events fired during a single selection gesture. My code uses a timer along with a counter to only do the programmatic selection when there are no longer any pending touch generated selection changed events.
int _selectCounter = 0;
const int SELECT_TIMER_LENGTH = 500;
async private void TextBox1_SelectionChanged(object sender, RoutedEventArgs e)
{
// _selectCounter is the number of selection changed events that have fired.
// If you are really paranoid, you will want to make sure that if
// _selectCounter reaches MAX_INT, that you reset it to zero.
int mySelectCount = ++_selectCounter;
// start the timer and wait for it to finish
await Task.Delay(SELECT_TIMER_LENGTH);
// If equal (mySelectCount == _selectCounter),
// this means that NO select change events have fired
// during the delay call above. We only do the
// programmatic selection when this is the case.
// Feel free to adjust SELECT_TIMER_LENGTH to suit your needs.
if (mySelectCount == _selectCounter)
{
this.TextBox2.Select(this.TextBox1.SelectionStart, this.TextBox1.SelectionLength);
}
}

WPF USB card reader keyDown

I have problem with reading text from card reader connected to USB.
I have method in window:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
Key k = (Key)e.Key;
textBoxLogin.Text += k.ToString();
}
Problem is that, it simulates all pressed keys so if in my magnetic card i have something like:
!EXAMPLE,
that would read LeftShift1LeftShiftELeftShiftX etc..
Any solution how to change it?
Btw i know i can click on textBox and then read all from card reader, but that should work with disabled textBox.
Thank u for any answers!
I guess there is no easy way to convert keys to a string. If you really want to get the text from the Window_KeyDown callback, I think you'll have to code your own converter.
The source of your problem comes from the input : why does the card contains a series of keydown events rather than directly the characters ?

Switch after 5 characters

I'm trying to swipe a card and after the 5 characters are entered I want it to go to the next textfield. I'm scanning a card.
Currently I have:
private void membernumber1_TextChanged(object sender, EventArgs e)
{
}
But this changes it right after it enters one character, is there anyway to make it switch after 5 characters entered?
Just count the number of characters in the Text property. Using a counter won't work if they use the backspace key.
if( membernumber1.Text.Length == 5 )
SwitchFocus();
Be aware though that this may not work for text that was pasted into the control (i.e., if it was > 5 characters). You'll need proper validation for that case or you can just disable pasting, but validation is preferable as there are certainly other restrictions like being all numeric.

Categories