Winforms按键和条形码扫描仪

neg*_*nbe 4 c# wndproc barcode-scanner winforms

我在WPF项目中使用键盘挂钩成功地使用了条形码扫描仪,如下所示(我略过了一些细节,但是基本上,我可以依靠我知道哪个键盘是我的扫描仪的事实)。

/// <summary>
/// Add this KeyboardHook to a window
/// </summary>
/// <param name="window">The window to add to</param>
public void AddHook(Window window) {
  if (form == null)
    throw new ArgumentNullException("window");
  if (mHwndSource != null)
    throw new InvalidOperationException("Hook already present");

  WindowInteropHelper w = new WindowInteropHelper(window);
  IntPtr hwnd = w.Handle;
  mHwndSource = HwndSource.FromHwnd(hwnd);
  if (mHwndSource == null)
    throw new ApplicationException("Failed to receive window source");

  mHwndSource.AddHook(WndProc);

  RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];

  rid[0].usUsagePage = 0x01;
  rid[0].usUsage = 0x06;
  rid[0].dwFlags = RIDEV_INPUTSINK;
  rid[0].hwndTarget = hwnd;

  if (!RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
    throw new ApplicationException("Failed to register raw input device(s).");
}
Run Code Online (Sandbox Code Playgroud)

然后,该方法处理WM_INPUT消息以检索有关发生的任何键盘事件的信息,并在该事件来自已知的条形码扫描器的情况下进行相应的处理。

现在的问题是,在Winforms中,我不应该使用钩子,而是按此处所述重写WndProc ,但是我需要某种方式来努力了解如何使用WndProc,因为我需要知道:

a)我真的需要在WndProc方法中处理什么事件

b)我如何识别触发事件的设备

任何帮助将不胜感激!干杯!

neg*_*nbe 5

我使用以下方法结束了:

public class BarcodeScannedEventArgs : EventArgs {

    public BarcodeScannedEventArgs(string text) {
      mText = text;
    }
    public string ScannedText { get { return mText; } }

    private readonly string mText;
  }

  public class BarCodeListener : IDisposable {
    DateTime _lastKeystroke = new DateTime(0);
    string _barcode = string.Empty;
    Form _form;
    bool isKeyPreview;

    public bool ProcessCmdKey(ref Message msg, Keys keyData) {
      bool res = processKey(keyData);
      return keyData == Keys.Enter ? res : false;
    }

    protected bool processKey(Keys key) {
      // check timing (>7 keystrokes within 50 ms ending with "return" char)
      TimeSpan elapsed = (DateTime.Now - _lastKeystroke);
      if (elapsed.TotalMilliseconds > 50) {
        _barcode = string.Empty;
      }

      // record keystroke & timestamp -- do NOT add return at the end of the barcode line
      if (key != Keys.Enter) {
        _barcode += (char)key;
      }
      _lastKeystroke = DateTime.Now;

      // process barcode only if the return char is entered and the entered barcode is at least 7 digits long.
      // This is a "magical" rule working well for EAN-13 and EAN-8, which both have at least 8 digits...
      if (key == Keys.Enter && _barcode.Length > 7) {
        if (BarCodeScanned != null) {
          BarCodeScanned(_form, new BarcodeScannedEventArgs(_barcode));
        }
        _barcode = string.Empty;
        return true;
      }
      return false;
    }

    public event EventHandler<BarcodeScannedEventArgs> BarCodeScanned;

    public BarCodeListener(Form f) {
      _form = f;
      isKeyPreview = f.KeyPreview;
      // --- set preview and register event...
      f.KeyPreview = true;
    }

    public void Dispose() {
      if (_form != null) {
        _form.KeyPreview = isKeyPreview;
        //_form.KeyPress -= KeyPress_scanner_preview;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,将以下代码行添加到正在侦听扫描仪的表单中:

private BarCodeListener ScannerListener;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
  bool res = false;
  if (ScannerListener != null) {
    res = ScannerListener.ProcessCmdKey(ref msg, keyData);
  }
  res = keyData == Keys.Enter ? res : base.ProcessCmdKey(ref msg, keyData);
  return res;
}
Run Code Online (Sandbox Code Playgroud)