如果我使用以下代码:
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'。我该怎么攻击这个?我将采用输入字符串并为我正在尝试开发的宏播放器创建虚拟按键。
答案 0 :(得分:5)
这似乎是错误的做法。您考虑过使用SendKeys吗?
答案 1 :(得分:1)
Keys
枚举不是按下该键时生成的字符的字符值的直接副本。有时它是,但有时它不是。 documentation:
此类包含用于处理键盘输入的常量。键由键值标识,键值由键代码和组合成单个整数值的一组修饰符组成。键值的左侧四位数字包含键码(与Windows虚拟键码相同)。键值的四个右数位包含SHIFT,CONTROL和ALT键的修饰符位。
答案 2 :(得分:1)
答案是为您需要的字符构建反向查找表。代码可以进一步优化,但它是自我解释的。如果需要,您可以显式添加特殊字符。
你也可以同时建立一个字典,以便在你喜欢的时候走另一条路。多键字符需要一个简单的扩展,但无论如何它们都不会直接映射到Keys。 如果您需要,请仔细阅读和扩展:
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);