将 String 或 Char 转换为 Keys 对象

发布于 2024-09-27 20:16:32 字数 341 浏览 5 评论 0原文

如果我使用以下代码:

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

If I use the following code:

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

I can get a correct conversion for uppercase letters only. The problem is, I need to be able to replicate lower case characters as well, and I am getting conversion errors on them. For instance, 'e' converts to 'NumPad5', where 'E' converts correctly to 'E'. How do I attack this? I'm going to be taking input strings and creating virtual key presses for a macro player I am trying to develop.

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

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

发布评论

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

评论(3

浅唱々樱花落 2024-10-04 20:16:32

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

That seems like the wrong approach. Have you considered using SendKeys?

倥絔 2024-10-04 20:16:32

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

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

The Keys enumeration is not a straight copy of the character values of the character generated when the key is pressed. Sometimes it is, but sometimes it is not. The way the value is encoded for each keypress is described in the documentation:

This class contains constants to use for processing keyboard input. Keys are identified by key values, which consist of a key code and a set of modifiers combined into a single integer value. The four left digits of a key value contain the key code (which is the same as a Windows virtual key code). The four right digits of a key value contain modifier bits for the SHIFT, CONTROL, and ALT keys.

嘿嘿嘿 2024-10-04 20:16:32

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

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

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

The answer is to build a reverse lookup table for the chars you need. The code could be optimized further but it is self explanatory. You could add special chars explicitly if needed.

You could also simultaneously build a dictionary to go the other way also should it take your fancy. Multi-key chars would require a trivial extension but they don't map directly to Keys anyway.
For your perusal and possible extension should you require it:

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