DataGrid PreviewTextInput事件从输入中删除控制字符

J C*_*man 5 c# wpf xaml wpf-controls

我有一个带有数据网格的WPF窗口.我试图从Symbol扫描仪中捕获通过虚拟楔形发送的字符串.对于应用程序,它看起来像是键入了字符.该字符串以ASCII 1(SOH)开头.

当窗口具有焦点的窗口的PreviewTextInput接收SOH与所有其他人类可读和非人类可读值一起. 但是,当数据网格具有焦点时,非人类可读字符将被剥离.

如果我在窗口上有PreviewKeyDown或PreviewKeyUp,则无论焦点是什么,字符都会正确显示.因此,数据网格沿途的某处将其剥离.不幸的是因为KeyDown/KeyUp没有显示ASCII字符,所以我不能使用这些事件而不必编写某种解析算法.

谁能告诉我我能做些什么来让那些非人类可读的控制字符始终发送到PreviewTextInput?或者如何解析PreviewKeyDown中的所有字符?

编辑:

当窗口具有焦点时:

Window PreviewKeyDown - LeftCtrl
Window PreviewKeyDown - A
Window PreviewTextInput - <SOH>
Window PreviewKeyDown - Oem6
Window PreviewTextInput - ]
Window PreviewKeyDown - LeftShift
Window PreviewKeyDown - C
Window PreviewTextInput - C
Run Code Online (Sandbox Code Playgroud)

当数据网格具有焦点时:

Window PreviewKeyDown - LeftCtrl
DataGrid PreviewKeyDown - LeftCtrl
Window PreviewKeyDown - A
DataGrid PreviewKeyDown - A
Window PreviewKeyDown - Oem6
DataGrid PreviewKeyDown - Oem6
Window PreviewTextInput - ]
Window PreviewKeyDown - LeftShift
DataGrid PreviewKeyDown - LeftShift
Window PreviewKeyDown - C
DataGrid PreviewKeyDown - C
Window PreviewTextInput - C
Run Code Online (Sandbox Code Playgroud)

Ala*_*lan 1

好吧,我知道这可能不太符合您的期望,但我有一些为某些 Symbol 条形码扫描仪编写软件的经验。在一个应用程序中,我们让用户扫描他们的徽章以验证自己的身份以覆盖某些条件。我们希望用户“扫描”他们的徽章,而不能使用键盘输入数字。我记得我们花了很长时间试图弄清楚如何让输入不像是通过键盘输入的那样。我相信我们能够从Symbol条码扫描仪手册中扫描一些配置代码,将其配置为一个USB设备,我们可以根据需要打开并处理其输入。这种方法对我们来说要好得多。

你有考虑过尝试类似的事情吗?

MSDN 论坛上的这篇文章似乎相关(Converting Key To ASCII

条形码阅读器通常可以在两种模式下运行。一是它充当键盘楔子,生成击键,就像用户键入代码一样。另一种是应用程序通常通过串行端口直接接收扫描的代码。您已将阅读器切换到生成适合后一种方式的代码的模式。Ctrl+B 是控制码,SOH(Start Of Header)。它用于使程序与阅读器同步,SOH表示扫描的开始,您可以使用它来重置缓冲区索引。

您需要将阅读器配置为键盘楔模式,在该模式下它不会生成控制字符。如有必要,您仍然可以通过编写 KeyDown 事件处理程序(用于检测 SOH)和 KeyPressed 事件处理程序(用于检测扫描代码)来使其工作。避免尝试将您在 KeyDown 中看到的击键转换为字符,KeyPressed 已经为您做到了这一点。

我相信这可能适合您转换为 ASCII:

[DllImport("user32.dll")]
    static extern int ToAsciiEx(uint uVirtKey, uint uScanCode, byte[] lpKeyState, byte[] arr, uint uFlags, IntPtr hkl);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetKeyboardState(byte[] lpKeyState);


    private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        byte[] keyboardState = new byte[256];
        int keyCode = KeyInterop.VirtualKeyFromKey(e.Key);
        byte[] arr = new byte[4];
        GetKeyboardState(keyboardState );
        Debug.WriteLineIf(ToAsciiEx((uint)keyCode, 0, keyboardState, arr, 0, IntPtr.Zero) > 0, ASCIIEncoding.ASCII.GetString(arr));
    }
Run Code Online (Sandbox Code Playgroud)