2

如果我使用以下代码:

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”。我该如何攻击这个?我将为我正在尝试开发的宏播放器获取输入字符串并创建虚拟按键。

4

3 回答 3

5

这似乎是错误的做法。您是否考虑过使用SendKeys

于 2010-10-18T20:10:45.760 回答
1

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

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

于 2010-10-18T20:12:32.293 回答
1

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

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

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);
于 2017-06-21T23:27:28.623 回答