1

我想将给定的一组System.Windows.Forms.Keys和 a翻译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的可选组合的“正常”转换为 a 的方法。多次连续调用必须产生相同的字符。没有硬编码的键盘布局,定义了要使用的布局。Keys.ShiftKeys.AltKeys.ControlSystem.CharInputLanguage

作为帮助理解我想要做的事情:KeyPressEventArgs仅使用给定的KeyEventArgs(和正确的InputLangauge)生成一个。

死键不应该影响FromKeys

4

2 回答 2

5

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

    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);
于 2011-06-05T21:43:25.077 回答
0

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

另一种可能性,虽然涉及很多,但是将您的事件转换为与SendKeys兼容的字符串,然后将字符串发送到您的应用程序。

您必须为主线程设置文化并使用单独的线程进行发送。

我不知道这样的事情会有多好,而且尝试它有点贵(就时间而言)。

于 2011-06-02T15:08:47.367 回答