نقل قول نوشته شده توسط the king مشاهده تاپیک
چیزی که من به عنوان بارکد خوان میشناسم شبیه صفحه کلید عمل می کنه و کلید ها رو با یک سرعت خاصی میفرسته و انتهاش ممکنه کلید Enter رو حتی طبق تنظیماتش کلید دیگری رو بفرسته یا اصلا کلیدی در انتها نفرسته که واقعا برای برنامه نویس خیلی مهم نیست.
طبعا اگر شما از ابتدا یک کنترل Focus شده مثل TextBox داشته باشید و دخالتی هم نکنید محتویات اون TextBox بصورت خودکار پر میشه، اما چند تا مساله هست :
  • اگر قبل از اینکه بارکد خوان کارشو شروع کنه اون Focus روی کنترل رو نکرده باشید طبعا کلید ها هم در جای مناسب دریافت نمیشه، پس فایده نداره که بعد ارسال کلید Enter تازه بفکر Focus بیافتیم. باید قبل از ارسال اولین کاراکتر Focus شده باشه.
  • اگر در حین ارسال بارکد به هر دلیلی Focus تغییر کنه یا کاربر کلیدی فشار بده، اعم از اینکه کاربر دستش به ماوس و صفحه کلید بخوره یا برنامه ای هوس نشون دادن پیامی بکنه ارسال نیمه کاره میمونه و بارکد بصورت کامل دریافت نمیشه.
  • اگه توقع داشته باشیم که حتما در انتها کلید Enter ارسال بشه شاید اصلا بارکد خوان مدل فلان همچین کاری رو نکنه و تا ابد منتظر بمونیم یا مجبور بشیم خودمون بارکد دریافتی رو دستی با کلیک یا Enter تایید کنیم.


پس چه کنیم؟ کلید ها رو بدون توجه به کنترلی که Focus داره در حافظه مجزایی دریافت کنیم و هر وقت دیدیم بعد یک مدت زمانی کلید جدیدی دریافت نشد یا کلید Enter دریافت شد، دریافت رو خاتمه یافته فرض کنیم و حالا از بارکد هر جا لازمه استفاده کنیم.
برای ما مهم نیست که Focus روی چه کنترلی باشه چون هر چی کلید دریافت میشه قبل از اینکه به کنترل های روی فرم برسه توسط خود فرم پردازش میکنیم، حتی وقتی یک Button روی فرم Focus داره Enter اول توسط ما پردازش میشه :

public partial class Form1 : Form
{
private StringBuilder _barcode = new StringBuilder();
private DateTime _lastTime;
private const int Timeout = 1000; // 1000 milliseconds
private const string BarcodeChars = "0123456789";

public Form1()
{
InitializeComponent();
}

private void BarcodeReceived(string barcode)
{
textBox1.Text = barcode;
}

private void Form1_Load(object sender, EventArgs e)
{
KeyPreview = true;
var timer = new Timer { Interval = 200, Enabled = true };
timer.Tick += timer_Tick;
}

private void timer_Tick(object sender, EventArgs e)
{
if (_barcode.Length > 0)
{
if (DateTime.Now.Subtract(_lastTime).TotalMillisecond s >= Timeout)
{
BarcodeReceived(_barcode.ToString());
_barcode.Length = 0;
}
}
}

protected override bool ProcessDialogKey(Keys keyData)
{
if ((keyData == Keys.Return) && (_barcode.Length > 0))
{
BarcodeReceived(_barcode.ToString());
_barcode.Length = 0;
return true;
}
return base.ProcessDialogKey(keyData);
}

protected override void OnKeyPress(KeyPressEventArgs e)
{
if (BarcodeChars.IndexOf(e.KeyChar) >= 0)
{
_lastTime = DateTime.Now;
_barcode.Append(e.KeyChar);
e.Handled = true;
}
base.OnKeyPress(e);
}
}


من Timeout رو روی یک ثانیه و کاراکتر های بارکد رو 0 الی 9 در نظر گرفتم، اگه لازمه کاراکتر های دیگه داخل بارکد رو به BarcodeChars اضافه کنید.
این روش رو به نوعی دیگه تست زدم و برام جالب نبود و در شرایطی درست کار نمیکرد !
من روی برنامه های حسابداری که تست زدم همه رو درست دریافت میکرد و نشون میداد
یچیزی شبیه به کاری که اونت receive پورت سریال ولی با این تفاوت که براش مهم نیست چه پورتی کانکت شده و چی میفرسته