【问题标题】:Translate Keys to char将键转换为字符
【发布时间】:2013-05-29 22:33:26
【问题描述】:

我想将一组给定的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

【问题讨论】:

  • 这是作业还是作业?
  • @ChrisF 那门课是什么? =D 不,它只是我正在处理的一个项目,其中我的事件等于 WinForms 中的KeyDown,但不是KeyPress ...
  • 只是“注意 Keys.Shift 和 Keys.ShiftKey”这句话让我印象深刻,因为它会写在作业上 ;)
  • 啊,好吧 :D,我实际上坐了很长时间,这是我掉进的陷阱。Keys.Shift 是 .NET 的说法,其他 Keys 被修改为这个。而Keys.ShiftKey 是键盘上真正的键。

标签: .net winforms keycode


【解决方案1】:

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

    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);

【讨论】:

  • 谢谢,这很好(在简单的情况下),但我不能依赖GetKeyboardState,但可以使用修饰符生成该状态数组(请参阅更新的问题,我正在尝试为此找到一些代码)。到目前为止没有什么工作:死键 正在弄乱键盘缓冲区,并且可以更改对 FromKeys 的调用结果。所以:FromKeys(Keys.A, ...) 应该总是导致'a'
  • @ordag - 是的,您可以模拟 GetKeyboardState,但我不确定是否真正理解您的意思。在我的测试中,FromKeys(Keys.A, ...) 总是返回一个 'a' - 我的测试来自一个真正的 KeyEventArg。
  • 我不知道你键盘上的Keys.Oem5 是什么,但是在FromKeys(Keys.Oem5, InputLanguage.CurrentInputLanguage) 之后,FromKeys(Keys.A, InputLanguage.CurrentInputLanguage) 调用会导致'â'。这是由键盘缓冲区引起的,它改变了结果,但不能刷新,因为这会影响其他应用程序。 (因此对FromKeys 的调用应该独立于任何当前键盘状态)
  • 您的解决方案运行良好。但是,如果缓冲区 (可能来自正常的击键) 中已经有一个 死键,它会干扰FromKeys .. 并且仅将其删除不是一种选择,因为那样会影响程序/用户超出方法的范围。
  • 仍然没有找到更好的解决方案,谢谢(不过,死键会搞砸一切)
【解决方案2】:

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

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

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

我不知道这样的方法效果如何,而且尝试起来有点贵(就时间而言)。

【讨论】:

  • 我尝试了 ToUnicodeEx 并且它的部分工作良好......仍然存在一些问题,例如重音和键盘布局缓冲区。
猜你喜欢
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
  • 1970-01-01
  • 2013-10-05
相关资源
最近更新 更多