Я работаю с экранной клавиатурой, которой нужно отправлять нажатия клавиш сторонним приложениям. Они работают на Windows XP. Небольшой набор символов, которые недоступны на американской английской клавиатуре, должен поддерживаться (например, «å» или ñ). После просмотра SendInput казалось, что самым безопасным будет отправить шестнадцатеричное значение Unicode символа в виде последовательности нажатий клавиш. Я написал код, который отправляет события нажатия клавиши «Alt» и «Add», за которыми следуют события нажатия клавиши «вниз» и «вверх» для последовательности символов Unicode из четырех символов с клавишей Alt «ORed», а затем, наконец, события «добавления» и «Alt». В моем приложении C # test. Я использую KeyPreview и, конечно же, все события проходят, однако все, что я получаю, это звуковой сигнал, без символа. Я получил ту же информацию от ввода нажатий клавиш вручную, информация KeyPreview идентична, и появляется символ.
Можно ли использовать SendInput таким образом? Я не использовал ловушку для проверки данных, но я видел посты, которые указывают, что к событиям SendInput прикреплен какой-то «введенный» флаг, может быть, это приводит к сбою последовательности?
Этот демонстрационный код успешно отправляет ключевые события, но последовательность ключевых событий, предназначенных для генерирования символа Unicode, не выполняется.
private const uint KEYEVENTF_KEYDOWN = 0x0000;
private const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
private const uint KEYEVENTF_KEYUP = 0x0002;
private const int INPUT_KEYBOARD = 1;
[DllImport ("user32.dll", SetLastError = false)]
static extern IntPtr GetMessageExtraInfo ();
[DllImport ("user32.dll", SetLastError = true)]
static extern uint SendInput (uint nInputs, [MarshalAs (UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, int cbSize);
[StructLayout (LayoutKind.Sequential, Size = 24)]
private struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout (LayoutKind.Explicit)]
private struct INPUT
{
[FieldOffset (0)]
public int type;
[FieldOffset (4)]
public KEYBDINPUT ki;
}
private void PressKey (Keys k)
{
PressKeyDown (k);
PressKeyUp (k);
}
private void PressKeyDown (Keys k)
{
INPUT input = new INPUT ();
input.type = INPUT_KEYBOARD;
input.ki.wVk = (byte)k;
input.ki.wScan = 0;
input.ki.time = 0;
uint flags = KEYEVENTF_KEYDOWN;
if ((33 <= (byte)k && (byte)k <= 46) || (91 <= (byte)k) && (byte)k <= 93)
flags |= KEYEVENTF_EXTENDEDKEY;
input.ki.dwFlags = flags;
input.ki.dwExtraInfo = GetMessageExtraInfo ();
Output ("Sending key down {0}. Flags:{1}", k, flags);
INPUT[] inputs = new INPUT[] { input };
uint result = SendInput ((uint)inputs.Length, inputs, Marshal.SizeOf (typeof (INPUT)));
if ((uint)inputs.Length != result)
MessageBox.Show ("PressKeyDown result = " + Marshal.GetLastWin32Error ());
}
private void PressKeyUp (Keys k)
{
INPUT input = new INPUT ();
input.type = INPUT_KEYBOARD;
input.ki.wVk = (byte)k;
input.ki.wScan = 0;
input.ki.time = 0;
uint flags = KEYEVENTF_KEYUP;
if ((33 <= (byte)k && (byte)k <= 46) || (91 <= (byte)k) && (byte)k <= 93)
flags |= KEYEVENTF_EXTENDEDKEY;
input.ki.dwFlags = flags;
input.ki.dwExtraInfo = GetMessageExtraInfo ();
Output ("Sending key up {0}", k);
INPUT[] inputs = new INPUT[] { input };
uint result = SendInput ((uint)inputs.Length, inputs, Marshal.SizeOf (typeof (INPUT)));
if ((uint)inputs.Length != result)
MessageBox.Show ("PressKeyUp result = " + Marshal.GetLastWin32Error ());
}
private void TestSend ()
{
System.Threading.Thread.CurrentThread.Join (1000);
Keys k = Keys.Menu;
PressKeyDown (k);
System.Threading.Thread.Sleep (100);
k = Keys.Add;
k |= Keys.Alt;
PressKeyDown (k);
System.Threading.Thread.Sleep (100);
k = Keys.NumPad0;
k |= Keys.Alt;
PressKey (k);
System.Threading.Thread.Sleep (100);
k = Keys.NumPad0;
k |= Keys.Alt;
PressKey (k);
System.Threading.Thread.Sleep (100);
k = Keys.E;
k |= Keys.Alt;
PressKey (k);
System.Threading.Thread.Sleep (100);
k = Keys.NumPad5;
k |= Keys.Alt;
PressKey (k);
System.Threading.Thread.Sleep (100);
PressKeyUp (Keys.Add);
PressKeyUp (Keys.Menu);
}