【问题标题】:Convert String or Char to Keys object将 String 或 Char 转换为 Keys 对象
【发布时间】:2011-04-27 03:37:02
【问题描述】:

如果我使用以下代码:

for (int i = 0; i < text.Length; i++)
    {
        char c = text[i];
        Keys k = (Keys)(byte)c;
        MessageBox.Show(c.ToString() + "|" + k.ToString());
    }

我只能正确转换大写字母。问题是,我还需要能够复制小写字符,并且我遇到了转换错误。例如,“e”转换为“NumPad5”,其中“E”正确转换为“E”。我该如何攻击这个?我将获取输入字符串并为我正在尝试开发的宏播放器创建虚拟按键。

【问题讨论】:

  • 你可以做一个 text.ToUpper()[i],而不是 text[i],或者... Keys key = ( c >= 'a' && c

标签: c# macros key keystroke


【解决方案1】:

这似乎是错误的方法。你有没有考虑过使用SendKeys

【讨论】:

  • 如果可以的话,我会给你+100万。这比我想象的要容易得多。我刚刚使用了SendKeys.SendWait(text);,它完全符合我的要求!
  • 如果目标窗口不处理 WM 命令,SendKeys 会抛出异常。
【解决方案2】:

Keys 枚举不是按键按下时生成的字符的字符值的直接副本。有时是,但有时不是。 documentation 中描述了每个按键的值编码方式:

此类包含用于处理键盘输入的常量。键由键值标识,键值由键代码和组合成单个整数值的一组修饰符组成。键值的左四位包含键码(与 Windows 虚拟键码相同)。键值的右四位数字包含 SHIFT、CONTROL 和 ALT 键的修饰符位。

【讨论】:

    【解决方案3】:

    答案是为您需要的字符建立一个反向查找表。代码可以进一步优化,但它是不言自明的。如果需要,您可以显式添加特殊字符。

    如果您喜欢它,您也可以同时构建一个字典以另辟蹊径。多键字符需要一个简单的扩展,但它们无论如何都不会直接映射到键。 如果您需要,请仔细阅读和可能的扩展:

    using System.Windows.Forms;
    static ImmutableDictionary<char, Keys> CharVKeyLookup;
    static void PopulateVKeyCharDictionary(){
        var keyboardStateNormal = new byte[255]; //All keys up
        var keyboardStateShift = new byte[255];
        keyboardStateShift[(int)Keys.ShiftKey] = 0x80;
        var charlookup = new Dictionary<char, Keys>();
        for (var i = 1; i < (int) Keys.OemClear; i++){
            var keys = (Keys) i;
            //Verbose condition to ignore unnecessary conversions - probably a quicker way e.g. statically
            if (keys == Keys.Enter || keys == Keys.Tab || keys == Keys.Space
                    || (keys >= Keys.D0 && keys <= Keys.D9)
                    || (keys >= Keys.A && keys <= Keys.Z)
                    || (keys >= Keys.Multiply && keys <= Keys.Divide)
                    || (keys >= Keys.Oem1 && keys <= Keys.Oem102)){
                var normal = KeyCodeToUnicode(keys);
                var shift = KeyCodeToUnicode(keys, true);
                if (normal.Item2 == 1) //Ignore wierdos - extend this if you need it
                    charlookup[normal.Item1[0]]=keys;
                if (shift.Item2 ==1)
                    charlookup[shift.Item1[0]]=keys|Keys.Shift; //Incl shift mod
            }
        }
        charlookup['\n'] =  Keys.Return;
        charlookup['\r'] = Keys.Return;
        CharVKeyLookup = charlookup.ToImmutableDictionary();
    }
    /// <returns>string if it exists and return code. -1=dead char, 0=no translation, 1=1 char, 2=special char </returns>
    public static Tuple<string, int> KeyCodeToUnicode(Keys key, byte[] keyboardState){
        var scanCode = MapVKToScanCode(key);
        var result = new StringBuilder(10,10);
        var language = InputLanguage.CurrentInputLanguage.Handle;//Or other method such as GetKeyboardLayout
        var returnState = ToUnicodeEx(key, scanCode, keyboardState, result, 10, 0,  language);
        return new Tuple<string, int>(result.ToString(),returnState);
    }
    [DllImport("user32.dll")]
    internal static extern int ToUnicodeEx(Keys wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    internal static extern IntPtr GetKeyboardLayout(int dwLayout);
    

    【讨论】:

    • 这就是我一直在寻找的。太棒了,谢谢,我会调查的。
    • NP。它像地狱一样丑陋,但效果很好。并不是说这对于大多数应用程序来说是最好的主意,但是厌倦了看到人们说这是不可能的,并且这被标记为“正确”的答案。我想如果你不知道认为这是不可能的是多么令人欣慰?
    猜你喜欢
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多