C# 创建unicode字符的SendInput序列失败
我正在使用一个屏幕键盘,它需要向第三方应用程序发送按键。它们在Windows XP上运行。需要支持美式英语键盘上不可用的一小部分字符(如“å”或ñ)。在查看SendInput之后,似乎最安全的方法是将字符的十六进制unicode值作为键击序列发送。我编写的代码发送一个“Alt”和“Add”键关闭事件,然后是带有Alt键的四字符unicode序列的键关闭和向上事件,最后是“Add”和“Alt”键打开事件。在我的C#测试应用程序中。我正在使用KeyPreview,可以肯定的是,所有的事件都通过了,但是我得到的只是一声蜂鸣,没有字符。我已经从手动输入笔划中捕获了相同的信息,KeyPreview信息是相同的,并且字符出现 可以这样使用SendInput吗?我没有使用钩子来检查数据,但是我看到一些帖子表明SendInput事件附加了某种“注入”标志,也许这会导致序列失败 此演示代码成功发送密钥事件,但用于生成unicode字符的密钥事件序列失败C# 创建unicode字符的SendInput序列失败,c#,unicode,localization,keyboard,keyboard-events,C#,Unicode,Localization,Keyboard,Keyboard Events,我正在使用一个屏幕键盘,它需要向第三方应用程序发送按键。它们在Windows XP上运行。需要支持美式英语键盘上不可用的一小部分字符(如“å”或ñ)。在查看SendInput之后,似乎最安全的方法是将字符的十六进制unicode值作为键击序列发送。我编写的代码发送一个“Alt”和“Add”键关闭事件,然后是带有Alt键的四字符unicode序列的键关闭和向上事件,最后是“Add”和“Alt”键打开事件。在我的C#测试应用程序中。我正在使用KeyPreview,可以肯定的是,所有的事件都通过了,但
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);
}
private const keyevent f_KEYDOWN=0x0000;
private consuint keyevent f_EXTENDEDKEY=0x0001;
私有consuint keyevent fu KEYUP=0x0002;
专用常量输入键盘=1;
[DllImport(“user32.dll”,SetLastError=false)]
静态外部IntPtr GetMessageExtraInfo();
[DllImport(“user32.dll”,SetLastError=true)]
静态外部uint SendInput(uint nInputs,[Marshallas(UnmanagedType.LPArray,SizeConst=1)]输入[]pInputs,int cbSize);
[StructLayout(LayoutKind.Sequential,Size=24)]
私有结构KEYBDINPUT
{
公共卫生署;
公共无线传感器网络;
公共旗帜;
公共时间;
公共IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Explicit)]
私有结构输入
{
[字段偏移量(0)]
公共int类型;
[现场偏移(4)]
公钥输入;
}
专用无效按键(按键k)
{
按下向下键(k);
按KEYUP(k);
}
私有无效按向下键(键k)
{
输入=新输入();
input.type=输入\键盘;
input.ki.wVk=(字节)k;
input.ki.wScan=0;
input.ki.time=0;
uint flags=KEYEVENTF\u KEYDOWN;
如果((33您可以通过按住Alt键并在数字键盘上键入4位Unicode代码点来生成它们。å=Alt+0229,ñ=Alt+0241。使用Charmap.exe小程序查找其他代码。您可以通过按住Alt键并在数字键盘上键入4位Unicode代码点来生成它们。å=Alt+0229,ñ=Alt+0241。使用Charmap.exe小程序查找其他代码。显然,表示unicode字符的按键序列的处理是在无法通过SendInput访问的级别上完成的。我将代码更改为在dwFlags上设置unicode标志,并在wScan数据参数上设置unicode值。我已成功说服在使用几种欧洲和亚洲语言进行测试后,我发现这与多次击键方法产生的结果相同。显然,表示unicode字符的按键序列的处理是在无法通过SendInput访问的级别上完成的。我将代码更改为在dwFlags上设置unicode标志并设置wScan数据参数上的unicode值。在使用几种欧洲和亚洲语言进行测试后,我说服自己,这与多次击键方法产生的结果相同。使用System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Simulate
{
public class Simulate
{
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] input, Int32 sizeOfInputStructure);
[StructLayout(LayoutKind.Sequential, Size = 24)]
struct KEYBDINPUT
{
public UInt16 Vk;
public UInt16 Scan;
public UInt32 Flags;
public UInt32 Time;
public UInt32 ExtraInfo;
}
[StructLayout(LayoutKind.Explicit)]
private struct INPUT
{
[FieldOffset(0)]
public int Type;
[FieldOffset(4)]
public KEYBDINPUT ki;
}
public static void TextInput(string text)
{
char[] chars = text.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
UInt16 unicode = chars[i];
INPUT down = new INPUT();
down.Type = 1; //INPUT_KEYBOARD
down.ki.Vk = 0;
down.ki.Scan = unicode;
down.ki.Time = 0;
down.ki.Flags = 0x0004; //KEYEVENTF_UNICODE
down.ki.ExtraInfo = 0;
INPUT up = new INPUT();
up.Type = 1; //INPUT_KEYBOARD
up.ki.Vk = 0;
up.ki.Scan = unicode;
up.ki.Time = 0;
up.ki.Flags = 0x0004; //KEYEVENTF_UNICODE
up.ki.ExtraInfo = 0;
INPUT[] input = new INPUT[2];
input[0] = down;
input[1] = up;
SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
}
}
}
}
// Call the API :
Simulate.TextInput("AbCçDeFgĞhİiJkLmNoÖpQrSşTuÜvXyZ - äÄß_0123456789");
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Runtime.InteropServices;
名称空间模拟
{
公共类模拟
{
[DllImport(“USER32.DLL”,CharSet=CharSet.Unicode)]
静态外部UInt32 SendInput(UInt32 numberOfInputs,INPUT[]INPUT,Int32 SizeOfInput结构);
[StructLayout(LayoutKind.Sequential,Size=24)]
结构键输入
{
公共UInt16 Vk;
公共UInt16扫描;
32面国旗;
公共UInt32次;
公共UInt32外部信息;
}
[StructLayout(LayoutKind.Explicit)]
私有结构输入
{
[字段偏移量(0)]
公共int类型;
[现场偏移(4)]
公钥输入;
}
公共静态无效文本输入(字符串文本)
{
char[]chars=text.ToCharArray();
for(int i=0;i
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Runtime.InteropServices;
名称空间模拟
{
公共类模拟
{
[DllImport(“USER32.DLL”,CharSet=CharSet.Unicode)]