将键转换为字符

发布于 2024-11-11 17:02:21 字数 2092 浏览 1 评论 0原文

我想将一组给定的 System.Windows.Forms.Keys 和 System.Windows.Forms.InputLanguage 转换为相应的 System.Char >。

尝试了一些实验 MapVirtualKeyEx,但是有现在是考虑键盘状态的方法,并且 ToUnicodeEx 对于死键来说是一种痛苦。

我的目标是一个函数...

static char? FromKeys(Keys keys, InputLanguage inputLanguage)
{
    // As I think what can be helpful and I got trying to find a solution for this problem:
    Keys vkCode = keys & Keys.KeyCode;
    Keys modifiers = keys & Keys.Modifiers;

    byte[] keyboardState = new byte[256];

    keyboardState[vkCode] = 1 << 7;

    if (modifiers.HasFlag(Keys.Shift))
    {
        keyboardState[(int)Keys.ShiftKey] = 1 << 7;
    }

    if (modifiers.HasFlag(Keys.Control))
    {
        keyboardState[(int)Keys.ControlKey] = 1 << 7;
    }

    if (modifiers.HasFlag(Keys.Alt))
    {
        keyboardState[(int)Keys.Menu] = 1 << 7;
    }

    // [Put your code here]
}

...应该这样调用:

FromKeys(Keys.A | Keys.Shift, InputLanguage.CurrentInputLanguage); // = 'A'
FromKeys(Keys.Escape, InputLanguage.DefaultInputLanguage); // = null
FromKeys(Keys.Oemtilde, InputLanguage.FromCulture(new CultureInfo("de-DE"))); // = 'ö'
FromKeys(Keys.E | Keys.Control | Keys.Alt, InputLanguage.FromCulture(new CultureInfo("de-DE"))); // = '€'

(注意 Keys.ShiftKeys.ShiftKey!)

这个函数是什么样的?

我选择的答案应该提供一种转换“正常”System.Windows.Forms 的方法.Keys 以及可选的修饰符组合(Keys.ShiftKeys.AltKeys.Control) 到 System.Char。多次连续调用必须产生相同的字符。没有硬编码的键盘布局,InputLanguage 定义要使用的布局。

帮助理解我想要做什么:生成 KeyPressEventArgs仅给出 KeyEventArgs(以及正确的 InputLangauge)。

死键 应该不影响FromKeys

I want to translate a given set of System.Windows.Forms.Keys and a System.Windows.Forms.InputLanguage to the corresponding System.Char.

Tried some experiments with MapVirtualKeyEx, but there is now way to consider keyboard state, and ToUnicodeEx is a pain with dead keys.

My goal is a function ...

static char? FromKeys(Keys keys, InputLanguage inputLanguage)
{
    // As I think what can be helpful and I got trying to find a solution for this problem:
    Keys vkCode = keys & Keys.KeyCode;
    Keys modifiers = keys & Keys.Modifiers;

    byte[] keyboardState = new byte[256];

    keyboardState[vkCode] = 1 << 7;

    if (modifiers.HasFlag(Keys.Shift))
    {
        keyboardState[(int)Keys.ShiftKey] = 1 << 7;
    }

    if (modifiers.HasFlag(Keys.Control))
    {
        keyboardState[(int)Keys.ControlKey] = 1 << 7;
    }

    if (modifiers.HasFlag(Keys.Alt))
    {
        keyboardState[(int)Keys.Menu] = 1 << 7;
    }

    // [Put your code here]
}

... which should be called like this:

FromKeys(Keys.A | Keys.Shift, InputLanguage.CurrentInputLanguage); // = 'A'
FromKeys(Keys.Escape, InputLanguage.DefaultInputLanguage); // = null
FromKeys(Keys.Oemtilde, InputLanguage.FromCulture(new CultureInfo("de-DE"))); // = 'ö'
FromKeys(Keys.E | Keys.Control | Keys.Alt, InputLanguage.FromCulture(new CultureInfo("de-DE"))); // = '€'

(Be aware of Keys.Shift and Keys.ShiftKey!)

How would this function look like?

The answer I'll choose should provide a way to translate one "normal" System.Windows.Forms.Keys with an optional combination of the modifiers (Keys.Shift, Keys.Alt, Keys.Control) to a System.Char. Multiple successively calls have to result in the same character. No hardcoded keyboard layouts, the InputLanguage defines the layout to use.

As a help to understand what I'm trying to to: Generate a KeyPressEventArgs with just the KeyEventArgs (and the correct InputLangauge) given.

Dead keys should not affect FromKeys!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

昔日梦未散 2024-11-18 17:02:21

这是一段代码,似乎可以满足您的需求 - 如果我理解正确的话:-)

    public static char? FromKeys(Keys keys, InputLanguage inputLanguage)
    {
        return FromKeys(keys, inputLanguage, true);
    }

    private static char? FromKeys(Keys keys, InputLanguage inputLanguage, bool firstChance)
    {
        if (inputLanguage == null)
        {
            inputLanguage = InputLanguage.CurrentInputLanguage;
        }

        byte[] keyStates = new byte[256];

        const byte keyPressed = 0x80;
        keyStates[(int)(keys & Keys.KeyCode)] = keyPressed;
        keyStates[(int)Keys.ShiftKey] = ((keys & Keys.Shift) == Keys.Shift) ? keyPressed : (byte)0;
        keyStates[(int)Keys.ControlKey] = ((keys & Keys.Control) == Keys.Control) ? keyPressed : (byte)0;
        keyStates[(int)Keys.Menu] = ((keys & Keys.Alt) == Keys.Alt) ? keyPressed : (byte)0;

        StringBuilder sb = new StringBuilder(10);
        int ret = ToUnicodeEx(keys, 0, keyStates, sb, sb.Capacity, 0, inputLanguage.Handle);
        if (ret == 1)
            return sb[0];

        if (ret == -1)
        {
            // dead letter
            if (firstChance)
            {
                FromKeys(keys, inputLanguage, false);
            }
            return null;
        }
        return null;
    }

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int ToUnicodeEx(Keys wVirtKey, uint wScanCode, byte[] lpKeyState, StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);

Here is a piece of code that seems to do what you're looking for - if I understood it correctly :-)

    public static char? FromKeys(Keys keys, InputLanguage inputLanguage)
    {
        return FromKeys(keys, inputLanguage, true);
    }

    private static char? FromKeys(Keys keys, InputLanguage inputLanguage, bool firstChance)
    {
        if (inputLanguage == null)
        {
            inputLanguage = InputLanguage.CurrentInputLanguage;
        }

        byte[] keyStates = new byte[256];

        const byte keyPressed = 0x80;
        keyStates[(int)(keys & Keys.KeyCode)] = keyPressed;
        keyStates[(int)Keys.ShiftKey] = ((keys & Keys.Shift) == Keys.Shift) ? keyPressed : (byte)0;
        keyStates[(int)Keys.ControlKey] = ((keys & Keys.Control) == Keys.Control) ? keyPressed : (byte)0;
        keyStates[(int)Keys.Menu] = ((keys & Keys.Alt) == Keys.Alt) ? keyPressed : (byte)0;

        StringBuilder sb = new StringBuilder(10);
        int ret = ToUnicodeEx(keys, 0, keyStates, sb, sb.Capacity, 0, inputLanguage.Handle);
        if (ret == 1)
            return sb[0];

        if (ret == -1)
        {
            // dead letter
            if (firstChance)
            {
                FromKeys(keys, inputLanguage, false);
            }
            return null;
        }
        return null;
    }

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int ToUnicodeEx(Keys wVirtKey, uint wScanCode, byte[] lpKeyState, StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
余生一个溪 2024-11-18 17:02:21

我不确定这是否有效,但您可以查看 ToUnicodeEx。它允许您设置键盘状态以及输入区域设置。

另一种可能性,虽然相当复杂,是将您的事件转换为与 SendKeys,然后将字符串发送到您的应用程序。

您必须为主线程设置区域性并使用单独的线程来进行发送。

我不知道这样的东西效果如何,而且尝试它有点昂贵(就时间而言)。

I'm not certain this will work, but you might take a look at ToUnicodeEx. It lets you set the keyboard state as well as the input locale.

Another possibility, although pretty involved, would be to turn your events into strings that are compatible with SendKeys, and then send the string to your application.

You'd have to set the culture for the main thread and use a separate thread to do the sending.

I don't know how well something like that would work, and it's kind of expensive (in terms of time) to try it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文