keybd_event:全局击键模拟在c#控制台以意想不到的方式显示

本文关键字:控制台 意想不到 显示 方式 模拟 event 全局 keybd | 更新日期: 2023-09-27 17:53:22

当您打开控制台并按住a按钮一秒钟时会发生什么?

输出最好是aaaaaaaa +- a few a's。因此,当我模拟按下a按钮并在一秒钟后释放它时,如果发现这段代码的输出很奇怪:

static void Main(string[] args)
{
    keybd_event(0x41, 0, KEYEVENTF_KEYDOWN, 0);
    Thread.Sleep(1000);
    keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0);
    Console.ReadLine();
}

为单个a。好吧,我可以接受。我将做一个循环来重复这个任意次数。假设我需要5次使用a字符,我希望下面的代码就足够了:

static void Main(string[] args)
{
    const int VK_A = 0x41;
    for (int i = 0; i < 5; i++)
    {
        keybd_event(VK_A, 0, KEYEVENTF_KEYDOWN, 0);
        keybd_event(VK_A, 0, KEYEVENTF_KEYUP, 0);
        Thread.Sleep(200);
    }
    Console.WriteLine("done");
    Thread.Sleep(4000);
    Console.ReadLine();
}

我很惊讶输出是

done
aaaaa

请注意,"完成"是 a 's之前,我觉得很奇怪,当Console.ReadLine()到达....时,a 's同时出现好像那个语句触发了字母出现....如果您想自己尝试,您还需要:

[DllImport("user32.dll", EntryPoint = "keybd_event", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern void keybd_event(byte vk, byte bscan, uint flags, int extrainfo);
const int KEYEVENTF_KEYUP = 0x2;
const int KEYEVENTF_KEYDOWN = 0x0;

我有完全相同的问题与较新的功能SendInput。有人能给我解释一下这背后的逻辑吗?

keybd_event:全局击键模拟在c#控制台以意想不到的方式显示

听起来输出缓冲区在击键之间没有刷新。这里有一个类似的帖子:

c#或。net刷新键盘缓冲区

帖子指出,冲洗键盘实际上是不可能的。网上有一些关于如何做到这一点的帖子——大多数类似于:http://myarticles-csharpnetstuff.blogspot.com/2009/09/tip-flush-keyboard-buffer-in-c.html

并使用以下方法(从链接复制):

private static void FlushKeyboard()
{
     while (Console.In.Peek() != -1)
         Console.In.Read();
}

我个人不喜欢这种方式,因为你最终会做很多不必要的读操作。你到底想干什么?"aaaa"出现在"done"之前真的很重要吗?

——丹