在C和WINAPI中模拟键被按下
我正在做一个项目,我带了一个超级任天堂控制器,用Arduino驱动它。Arduino读取控制器上按下的按钮,并通过串行连接发送 我正在开发一个接收器程序,它将从串口读取数据,然后在Windows中模拟按键,这样我就可以在其他程序中使用控制器 问题是,我几乎什么都记下来了。除了一个问题。 我的模拟按键没有被按下 这是A按钮的代码(按钮处于低激活状态,因此按下时为“假”) 例如,当我在SNES控制器上按A时,记事本中将显示A。 当我按住SNES控制器上的A按钮时,记事本中会出现一个A,但终端会打印出按键正在被按住,就像我编程的那样 当按钮从未按下状态第一次按下时,它模拟按键。当按下按钮时,不会再调用模拟按键。然后,当SNES按钮被释放时,按键也被释放在C和WINAPI中模拟键被按下,c,winapi,keypress,C,Winapi,Keypress,我正在做一个项目,我带了一个超级任天堂控制器,用Arduino驱动它。Arduino读取控制器上按下的按钮,并通过串行连接发送 我正在开发一个接收器程序,它将从串口读取数据,然后在Windows中模拟按键,这样我就可以在其他程序中使用控制器 问题是,我几乎什么都记下来了。除了一个问题。 我的模拟按键没有被按下 这是A按钮的代码(按钮处于低激活状态,因此按下时为“假”) 例如,当我在SNES控制器上按A时,记事本中将显示A。 当我按住SNES控制器上的A按钮时,记事本中会出现一个A,但终端会打印出
既然在按下键和向上键之间有这段时间,为什么只打印一个字母,而不是像按住键盘反复打印一样?感谢所有响应者 我最终采用了另一种方法,这次改用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));
}
}
}
}