【问题标题】:Problems with barcode reading using PreFilterMessage使用 PreFilterMessage 读取条形码的问题
【发布时间】:2014-11-26 12:35:00
【问题描述】:

我的任务是从 Symbol LS2208 条码扫描仪读取条码。
扫描仪设置为默认设置,但前缀为 F13,后缀为“Enter”。使用此扫描仪模拟美式键盘。我的键盘是丹麦语,操作系统语言设置为丹麦语。
我喜欢独立于用户的区域设置。

现在我正在使用以下方法实现 IMessageFilter:

    private const int WM_KEYDOWN = 0x100;
    private List<Keys> keysSequence = new List<Keys>();
    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
            if (keyCode == Keys.F13)
            {
                ...
                return true;
            }
            if (keyCode == Keys.Enter)
            {
                ...
                string barcode = GenerateBarcode(keysSequence);
                return true;
            }

            keysSequence.Add(keyCode);
        }
    }

当接收到后缀“Enter”键时,键序列用于创建条形码字符串,方法为GenerateBarcode

    public static string GenerateBarcode(Keys[] captureKeysSequence)
    {
        StringBuilder barcodeBuffer = new StringBuilder();
        bool shift = false;
        bool altGr = false;
        foreach (Keys keyCode in captureKeysSequence)
        {
            if (keyCode == Keys.Shift || keyCode == Keys.ShiftKey)
            {
                shift = true;
                continue;
            }
            if (keyCode == (Keys.Control | Keys.Alt))
            {
                altGr = true;
                continue;
            }
            barcodeBuffer.Append(GetCharsFromKeys(keyCode, shift, altGr));
            shift = false;
            altGr = false;
        }
        return barcodeBuffer.ToString();
    }

我在这里处理 shift 和 altGr 键。

现在我的问题的原因是GetCharsFromKeys 方法:

    [DllImport("user32.dll")]
    public static extern int ToUnicodeEx(uint virtualKeyCode, uint scanCode,
            byte[] keyboardState,
            [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
            StringBuilder receivingBuffer,
            int bufferSize, uint flags, IntPtr dwhkl);

    public static string GetCharsFromKeys(Keys keys, bool shift, bool altGr)
    {
        var buf = new StringBuilder(256);
        var keyboardState = new byte[256];
        if (shift)
            keyboardState[(int)Keys.ShiftKey] = 0xff;
        if (altGr)
        {
            keyboardState[(int)Keys.ControlKey] = 0xff;
            keyboardState[(int)Keys.Menu] = 0xff;
        }

        // Because the Symbol LS2208 maps a US keyboard we need to convert the Keys correctly to chars
        ToUnicodeEx((uint)keys, 0, keyboardState, buf, buf.Capacity, 0, InputLanguage.FromCulture(new System.Globalization.CultureInfo("en-US")).Handle);

        return buf.ToString();
    }

我正在尝试将来自条形码扫描仪的键输入转换为字符串。对于大多数常见的字符来说,它可以正常工作(上下字符和数字),并且在键盘上的数字上方找到的一些特殊字符也可以正常工作(例如'$')。

但是当使用像“12 / 34 - 56”这样的条形码进行测试时,我最终会得到输出“12 - 34 = 56”?

我认为这与美国和丹麦键盘之间的映射有关,但我不知道为什么?
有人可以帮我完成这个转换吗?

【问题讨论】:

  • 之后尝试合成键盘状态是失败的鲸鱼。如果您尝试处理死键,尤其如此。只是不要这样做,当你得到keydown时生成角色。此时 Pinvoke GetKeyboardState() 以获得准确状态。
  • 感谢您回答@HansPassant。我不确定我是否理解正确,但我尝试按照您的建议使用GetKeyboardState 获取键盘状态,并将输出用作ToUnicodeEx 的输入。但仍然是相同的结果,奇怪的条形码输出。可以举个例子吗?

标签: c# keyboard barcode keycode imessagefilter


【解决方案1】:

我无法按照我想要的方式解决这个问题:
“通过使用条形码扫描仪设置来使用美式键盘,并独立于设置的 Windows 区域键盘设置接收字符。”

所以我不得不将我的要求限制在:
“条形码扫描仪和 Windows 必须具有相同的键盘设置。”

这让一切变得如此简单。我仍在实现 IMessageFilter 并同时使用 VM_KEYDOWN 和 VM_MSG。这是我使用的代码(虽然,仍然缺少一些错误/超时处理):

public class BarcodeScannerMessageFilter : IMessageFilter
{
    public event EventHandler<BarcodeScannerReadyEventArgs> BarcodeScannerReady;

    private bool barcodeStarted = false;
    private StringBuilder barcodeBuilder = new StringBuilder();

    public BarcodeScannerMessageFilter()
    {
        Application.AddMessageFilter(this);
    }

    #region IMessageFilter Members
    private const int WM_KEYDOWN = 0x100;
    private const int WM_MSG = 0x102;
    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN) // Use KeyDown to look for prefix and surfix
        {
            Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;

            if (!barcodeStarted) // Prevent F13 Capture until previous is ended
            {
                // Check for start capture key (F13)
                if (keyCode == Keys.F13)
                {
                    barcodeStarted = true;
                    return true;
                }
            }
            else
            {
                // Check for end capture key (Enter)
                if (keyCode == Keys.Enter)
                {
                    // Raise barcode capture event with barcode
                    RaiseBarcodeReadyEventAsync(barcodeBuilder.ToString());

                    // End sequence
                    barcodeBuilder.Clear();
                    barcodeStarted = false;
                    return true;
                }
            }
        }
        else if (m.Msg == WM_MSG) // Catch all char messages
        {
            char c = (char)m.WParam;
            // Else just append char to barcodeBuilder to generate barcode
            barcodeBuilder.Append(c);
            return true;
        }

        return false;
    }

    #endregion

    private void RaiseBarcodeReadyEventAsync(string barcode)
    {
        Task.Factory.StartNew(() =>
        {
            try
            {
                // Generate barcode
                Console.WriteLine("F13 activated barcode [" + barcode + "]");

                if (BarcodeScannerReady != null)
                {
                    BarcodeScannerReady(this, new BarcodeScannerReadyEventArgs(barcode));
                }
            }
            catch (Exception ex)
            {
                // Do some error logging if needed
                Console.WriteLine(ex);
            }
        });
    }
}

public class BarcodeScannerReadyEventArgs : EventArgs
{
    public string Barcode { get; private set; }

    public BarcodeScannerReadyEventArgs(string barcode)
    {
        this.Barcode = barcode;
    }
}

我希望这可以帮助其他人解决像我这样的问题。

【讨论】:

    猜你喜欢
    • 2012-09-25
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 2012-01-27
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多