首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用SendInput和C#模拟按键事件

用SendInput和C#模拟按键事件
EN

Stack Overflow用户
提问于 2012-04-29 19:32:07
回答 1查看 9.5K关注 0票数 3

遵循这个线程的建议:区分键盘真实按键和虚拟按键

我正在尝试创建一个程序,它将使用SendInput()方法发送键盘的按键事件。

然而,的问题是,当我试图模拟一个键按事件时-没有发生任何事情。到目前为止,是我的代码:

代码语言:javascript
运行
复制
    [DllImport("user32.dll")]
    static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);

    [StructLayout(LayoutKind.Sequential)]
    struct KEYBDINPUT
    {
        public short wScan; public int dwFlags;
        public int time; public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct INPUT
    {
        [FieldOffset(0)] public int type;
        [FieldOffset(8)]  public KEYBDINPUT ki; //x64 - 8, x32 - 4
    }

    const int KEYEVENTF_DOWN = 0; //key UP
    const int KEYEVENTF_EXTENDEDKEY = 0x0001;
    const int KEYEVENTF_KEYUP = 0x0002; //key UP
    const int KEYEVENTF_UNICODE = 0x0004;
    const int KEYEVENTF_SCANCODE = 0x0008; // scancode

    public void Send_Key(short Keycode)
    {
        INPUT[] InputData = new INPUT[1];
        InputData[0].type = 1;
        InputData[0].ki.wScan = Keycode;
        InputData[0].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
        InputData[0].ki.time = 0;
        InputData[0].ki.dwExtraInfo = IntPtr.Zero;
        SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
    }

为了破解扫描代码,我下载了这个线程中建议的程序:

https://superuser.com/questions/293609/windows-7-tool-to-capture-keyboard-scan-codes

根据这个程序- "a“键的代码我的键盘是"65”

当文本框文本被更改时,我的程序应该触发一个键按事件,所以如果我们输入"q“--文本应该更改为"q”加上send_key()的结果,即"qa":

代码语言:javascript
运行
复制
    private void textBox2_TextChanged(object sender, EventArgs e)
    {
        Send_Key(0x0065); // nothing happens (0x65 also fails)
    }

我做错什么了?将来,我将更改这段代码,以便指定键保持时间(在下行事件和向上事件之间)。但就目前而言,出于测试目的,我只模拟keyUP事件。

编辑: Hans,根据您的建议,这里是编辑--但不幸的是,它不起作用。

代码语言:javascript
运行
复制
 public void Send_Key(short Keycode)
        {
            INPUT[] InputData = new INPUT[1];
            InputData[0].type = 1;
            InputData[0].ki.wScan = Keycode;
            InputData[0].ki.dwFlags = KEYEVENTF_DOWN;
            InputData[0].ki.time = 0;
            InputData[0].ki.dwExtraInfo = IntPtr.Zero;

            uint intReturn = SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));

            if (intReturn == 0) //!=1
            {
                throw new Exception("Could not send keyDOWN: " + Keycode);
            }

            INPUT[] InputData2 = new INPUT[1];
            InputData2[0].type = 1;
            InputData2[0].ki.wScan = Keycode;
            InputData2[0].mi.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
            InputData2[0].ki.time = 0;
            InputData2[0].ki.dwExtraInfo = IntPtr.Zero;

            uint intReturn2 = SendInput(1, InputData2, Marshal.SizeOf(typeof(INPUT)));

            if (intReturn2 == 0) //!=1
            {
                throw new Exception("Could not send keyUP: " + Keycode);
            }
        }

没有错误..。也没有输出。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-04-29 19:54:02

但现在,出于测试目的,我只模拟keyUP事件

这是好的,我想,但这不会使Windows做任何事情。要生成击键,必须首先发送一个KEYDOWN。“等待时间”没有任何有用的效果,所以只需将两个SendInput调用放在同一个方法中即可。

您应该添加错误检查,winapi调用不会生成任何异常。如果函数返回0,则抛出一个Win32Exception。并将DllImport声明修正为SetLastError = true。

您可以通过设置superuser.com字段和省略KEYEVENTF_SCANCODE标志来避免使用在ki.wVk中找到的程序。这样就可以指定虚拟密钥而不是扫描代码。.NET键枚举类型为您提供所需的值。与Keys.A一样,生成A键的按键。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10375264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档