我有一些用C#编写的代码,允许用户扫描条形码和标签。文本更改为条形码的输入。我使用标签而不是文本框来防止用户用手指乱写错误的条形码-基本上禁用了任何键盘输入。
除扫描的条形码中包含字母字符外,其他所有方法均正常运行。如果条形码以字母字符开头并以字母字符结尾,则条形码根本不会扫描。
如果条形码以字母字符开头,但以数字字符结尾,则程序仅选择尾随的数字字符。
代码如下:
char cforKeyDown = '\0';
int _lastKeystroke = DateTime.Now.Millisecond;
List<char> _barcode = new List<char>();
bool UseKeyboard = false;
private void Form1_Load(object sender, EventArgs e)
{
this.ActiveControl = label1;
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
*/
// Bumped it up to 35[ms]
if (elapsed > 50)
_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.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 stroke time
_lastKeystroke = DateTime.Now.Millisecond;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//Debug.WriteLine("CS_Single_Label_Printer_KeyDown : " + (char)e.KeyCode);
cforKeyDown = (char) e.KeyCode;
}
我将问题缩小为以下事实:所扫描的字母数字条形码的字母部分为大写。我使用小写字母生成了测试条形码,并且一切正常进行,但这仍然无法解决问题,因为我必须扫描成千上万已打印的条形码,这些条形码中的大写字符已编码到条形码数据矩阵中。 >
是否有一种方法可以切换以上代码,以解决“字符| Shift'KeyData?
答案 0 :(得分:1)
答案是KeyCode返回按下的KEY。它不尊重密钥的大小写。使用Shift获取案例。以下是基于您提供的代码的工作示例。魔术在本地函数ToCharacter中。如果您愿意,还需要使用顶部的if语句来包含数字。
From1.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DesktopApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
char cforKeyDown = '\0';
int _lastKeystroke = DateTime.Now.Millisecond;
List<char> _barcode = new List<char>();
bool UseKeyboard = false;
private void Form1_Load(object sender, EventArgs e)
{
this.ActiveControl = InputBox;
this.InputBox.KeyDown += new KeyEventHandler(Form1_KeyDown);
this.InputBox.KeyUp += new KeyEventHandler(Form1_KeyUp);
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
char NotALetter = '-';
DebugBox.Items.Clear();
DebugBox.Items.Add($"KeyEventArgs->KeyCode = {e.KeyCode.ToString()}");
DebugBox.Items.Add($"KeyEventArgs->KeyData = {e.KeyData.ToString()}");
DebugBox.Items.Add($"KeyEventArgs->KeyValue = {e.KeyValue.ToString()}");
DebugBox.Items.Add($"KeyEventArgs->e.Shift = {e.Shift.ToString()}");
DebugBox.Items.Add($"ToCharacter = {ToCharacter(e) ?? NotALetter}");
char? ToCharacter(KeyEventArgs kea)
{
int DtoNumPadOffset = (int)(Keys.NumPad0 - Keys.D0);
if (kea.KeyCode < Keys.D0) return null; // Keys.D0 through Kyes.D9 are the Keys on the top row of the keyboard. D9 is right next to A in the enum type.
if (kea.KeyCode > Keys.NumPad9) return null;
if (kea.KeyCode > Keys.Z && kea.KeyCode < Keys.NumPad0) return null; //knocks out keys between Z and NumPad0
if (kea.Shift && kea.KeyCode < Keys.A) return null; // rejects special characters when numbers across the top are used with the <shift> key.
if (kea.KeyCode < Keys.A) return (char)kea.KeyCode;
if (kea.KeyCode > Keys.Z) return (char)((int)kea.KeyCode - DtoNumPadOffset);
return kea.Shift
? (char)kea.KeyCode
: char.ToLower((char)kea.KeyCode);
}
// 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
*/
// Bumped it up to 35[ms]
//if (elapsed > 2000)
if (e.KeyCode == Keys.Return)
{
InputBox.Text = String.Empty;
_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)
{
char? TestForCharacter = ToCharacter(e);
if (TestForCharacter != null)
{
//_barcode.Add((char) e.KeyData);
_barcode.Add((char)TestForCharacter);
}
}
OutputBox.Text = string.Concat(_barcode);
// 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));
OutputBox.Text = String.Format("{0}", BarCodeData);
}
//_barcode.Clear();
}
// update the last key stroke time
_lastKeystroke = DateTime.Now.Millisecond;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//Debug.WriteLine("CS_Single_Label_Printer_KeyDown : " + (char)e.KeyCode);
cforKeyDown = (char)e.KeyCode;
}
}
}
Form1.Designer.cs
namespace DesktopApp2
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.OutputBox = new System.Windows.Forms.TextBox();
this.InputBox = new System.Windows.Forms.TextBox();
this.DebugBox = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// OutputBox
//
this.OutputBox.Location = new System.Drawing.Point(52, 93);
this.OutputBox.Name = "OutputBox";
this.OutputBox.ReadOnly = true;
this.OutputBox.Size = new System.Drawing.Size(650, 22);
this.OutputBox.TabIndex = 1;
//
// InputBox
//
this.InputBox.Location = new System.Drawing.Point(52, 45);
this.InputBox.Name = "InputBox";
this.InputBox.Size = new System.Drawing.Size(650, 22);
this.InputBox.TabIndex = 2;
//
// DebugBox
//
this.DebugBox.FormattingEnabled = true;
this.DebugBox.ItemHeight = 16;
this.DebugBox.Location = new System.Drawing.Point(52, 131);
this.DebugBox.Name = "DebugBox";
this.DebugBox.Size = new System.Drawing.Size(650, 308);
this.DebugBox.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(716, 450);
this.Controls.Add(this.DebugBox);
this.Controls.Add(this.InputBox);
this.Controls.Add(this.OutputBox);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox OutputBox;
private System.Windows.Forms.TextBox InputBox;
private System.Windows.Forms.ListBox DebugBox;
}
}
用于处理KeyEventArgs的简洁助手类
Is *函数将键控代码分为多个范围,并检测(如果适用)移位状态。 To *函数产生最能代表事件中KeyCode的字符。 ToAlphaNumericAsciiCharacter只需将检测器与生产者配对即可。
public static class KeyEventArgs_Functions
{
public static bool Between(this Keys source, Keys lhv, Keys rhv)
{
return source >= lhv && source <= rhv;
}
public static bool IsLetterKeyBoardChar(this KeyEventArgs source)
{
return source.KeyCode.Between(Keys.A, Keys.Z);
}
public static bool IsNumberKeyBoardChar(this KeyEventArgs source)
{
return !source.Shift && source.KeyCode.Between(Keys.D0, Keys.D9);
}
public static bool IsNumber10KeyPadChar(this KeyEventArgs source)
{
return source.KeyCode.Between(Keys.NumPad0, Keys.NumPad9);
}
public static char ToLetterKeyBoardChar(this KeyEventArgs source) // Only returns a valid value if IsLetterKeyBoardChar returns true.
{
return source.Shift ? (char)source.KeyCode: char.ToLower((char)source.KeyCode);
}
public static char ToNumberKeyBoardChar(this KeyEventArgs source) // Only returns a valid value if IsNumberKeyBoardChar returns true.
{
return (char)source.KeyCode;
}
public static char ToNumber10KeyPadChar(this KeyEventArgs source) // Only returns a valid value if IsNumber10KeyPadChar returns true.
{
const int DtoNumPadOffset = (int)(Keys.NumPad0 - Keys.D0);
return (char)((int)source.KeyCode - DtoNumPadOffset);
}
public static char? ToAlphaNumericAsciiCharacter(this KeyEventArgs source)
{
if (source.IsLetterKeyBoardChar()) return source.ToLetterKeyBoardChar();
if (source.IsNumberKeyBoardChar()) return source.ToNumberKeyBoardChar();
if (source.IsNumber10KeyPadChar()) return source.ToNumber10KeyPadChar();
return null;
}
}