Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C和WINAPI中模拟键被按下_C_Winapi_Keypress - Fatal编程技术网

在C和WINAPI中模拟键被按下

在C和WINAPI中模拟键被按下,c,winapi,keypress,C,Winapi,Keypress,我正在做一个项目,我带了一个超级任天堂控制器,用Arduino驱动它。Arduino读取控制器上按下的按钮,并通过串行连接发送 我正在开发一个接收器程序,它将从串口读取数据,然后在Windows中模拟按键,这样我就可以在其他程序中使用控制器 问题是,我几乎什么都记下来了。除了一个问题。 我的模拟按键没有被按下 这是A按钮的代码(按钮处于低激活状态,因此按下时为“假”) 例如,当我在SNES控制器上按A时,记事本中将显示A。 当我按住SNES控制器上的A按钮时,记事本中会出现一个A,但终端会打印出

我正在做一个项目,我带了一个超级任天堂控制器,用Arduino驱动它。Arduino读取控制器上按下的按钮,并通过串行连接发送

我正在开发一个接收器程序,它将从串口读取数据,然后在Windows中模拟按键,这样我就可以在其他程序中使用控制器

问题是,我几乎什么都记下来了。除了一个问题。 我的模拟按键没有被按下

这是A按钮的代码(按钮处于低激活状态,因此按下时为“假”)

例如,当我在SNES控制器上按A时,记事本中将显示A。 当我按住SNES控制器上的A按钮时,记事本中会出现一个A,但终端会打印出按键正在被按住,就像我编程的那样

当按钮从未按下状态第一次按下时,它模拟按键。当按下按钮时,不会再调用模拟按键。然后,当SNES按钮被释放时,按键也被释放


既然在按下键和向上键之间有这段时间,为什么只打印一个字母,而不是像按住键盘反复打印一样?

感谢所有响应者

我最终采用了另一种方法,这次改用SendInput,现在它的效果非常好

至于我保持状态的原因,我认为如果按下按钮,我不想在每次轮询控制器时模拟另一次按键。所以我保持状态,这样,如果按下按钮,下一次它被轮询时,它仍然被按下,我就不会生成另一个按键。只有当控制器的最后一个状态显示它没有被按下时,才会生成它

while(1)
{
    prevState = buttonState;
    ReadFile(   hCOM,
                &buttonState.state_word,
                2,
                &bytesRead,
                NULL);

    for(i = 0; i < 12; i++)
    {
        if(!(buttonState.state_word & (1 << i)))
        {
            /* If previous state is not pressed, and current is pressed, simulate a keypress */
            if(prevState.state_word & (1 << i))
            {
                in[i].ki.dwFlags = KEYEVENTF_SCANCODE;
                SendInput(1,&in[i],sizeof(INPUT));
            }
        }
        else if(buttonState.state_word & (1 << i))
        {
            /* If previous state is pressed, and current is not pressed, simulate a key release */
            if(!(prevState.state_word & (1 << i)))
            {
                in[i].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
                SendInput(1,&in[i],sizeof(INPUT));
            }
        }
    }

}
while(1)
{
prevState=按钮状态;
读取文件(hCOM,
&按钮state.state\u单词,
2.
&拜特斯拉德,
无效);
对于(i=0;i<12;i++)
{

如果(!(buttonState.state_word&(1)
prevState
什么时候更新?听起来你希望按键是“typematic”的。我不知道这是否适用于Windows中的模拟键盘事件。你根本不需要维护按钮状态。当你有远程事件(keydown或keydup)时您需要直接调用
keybdu事件
而不需要任何检查和条件。使用您的逻辑,您只需在按下/释放时设置键。它不应该是:
如果(buttonState.state_word&B_A){keybdu event(0x41,0x41,KEYEVENTF_EXTENDEDKEY,0)}其他{keybdu event(0x41,0x41,KEYEVENTF EXTENDEDKEY | KEYEVENTF KEYUP,0)}
?我不明白你为什么需要检查以前的状态。任何信号去抖动都应该在固件中完成,而不是由PC完成。这听起来像是一个业余项目,但如果你想让它专业化,你应该将ReadFile()替换为ReadFileEx(),并使用Windows“异步I/O”。这反过来意味着线程不会像当前程序那样消耗100%的CPU。@Lundin:同步I/O不是已经解决了您通过异步创建的问题吗?@IInspectable您是什么意思?@Lundin:阻塞(同步)
ReadFile
调用不会在坐在那里等待数据到达时消耗CPU周期。正如所发布的,该程序不会像您建议的那样消耗100%的CPU(或多核设置下的任何部分)。只有当有2个或更多字节可从
hCOM
读取时,它才会唤醒。如果没有,线程将挂起。@Lundin:因为您将
ReadFile
与“异步I/O”进行对比,我假设一个
COMMTIMEOUTS
初始化会导致阻塞等待。如果仔细阅读问题,这个线程不能做任何有意义的事情(除了读取输入并从中生成输出)是它指定的设计目标。如果问题不同,您的反馈可能会更有帮助。
while(1)
{
    prevState = buttonState;
    ReadFile(   hCOM,
                &buttonState.state_word,
                2,
                &bytesRead,
                NULL);

    for(i = 0; i < 12; i++)
    {
        if(!(buttonState.state_word & (1 << i)))
        {
            /* If previous state is not pressed, and current is pressed, simulate a keypress */
            if(prevState.state_word & (1 << i))
            {
                in[i].ki.dwFlags = KEYEVENTF_SCANCODE;
                SendInput(1,&in[i],sizeof(INPUT));
            }
        }
        else if(buttonState.state_word & (1 << i))
        {
            /* If previous state is pressed, and current is not pressed, simulate a key release */
            if(!(prevState.state_word & (1 << i)))
            {
                in[i].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
                SendInput(1,&in[i],sizeof(INPUT));
            }
        }
    }

}