C++循环模拟按键,当按键被按下时。

3

我想制作一个小应用程序,当按下另一个键(在我的情况下是右侧控制键Right CTRL)时,它将持续模拟UP(↑箭头键)。

然而,我编写的代码每次只会发送一个UP - 当我按住Right CTRL时,它只会发送一个UP并停止。

需要注意的是,这个代码完全是根据我在网上找到的文档构建的,我从未编写过任何C++或其他语言的代码,所以任何建议都会对我有很大帮助。最初,我尝试在开启CAPS LOCK时实现此功能,但发现无论我尝试什么,获取键状态(开/关)都不起作用。

int main()
{
  // This structure will be used to create the keyboard
  // input event.
  INPUT ip;

  // Pause for 1 seconds.
  Sleep(1000);

  // Set up a generic keyboard event.
  ip.type = INPUT_KEYBOARD;
  ip.ki.wScan = 0; // hardware scan code for key
  ip.ki.time = 0;
  ip.ki.dwExtraInfo = 0;

  while(1){
      if(GetAsyncKeyState(VK_RCONTROL))
      {
            // Press the "UP arrow" key
            ip.ki.wVk = 0x26; // virtual-key code for the "UP arrow" key
            ip.ki.dwFlags = 0; // 0 for key press
            SendInput(1, &ip, sizeof(INPUT));

            Sleep(50);

            // Release the "UP arrow" key
            ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
            SendInput(1, &ip, sizeof(INPUT));

            Sleep(50);
      }
  }

  // Exit normally
  return 0;
}  
1个回答

1

GetAsyncKeyState不返回一个关于按键是按下还是抬起的布尔值,而是一个SHORT(一个16位整数,通常字面上是short)。

如果函数成功,则返回值指定自上次调用GetAsyncKeyState以来是否按下了按键以及按键当前是按下还是抬起状态。如果最高有效位被设置,则按键是按下的,如果最低有效位被设置,则表示在上一次调用GetAsyncKeyState之后按下了该按键。

那么这意味着什么?硬件中的“最高有效位”是实现定义的(位域的哪一端是最高有效位?),但我们可以将所有内容视为左侧的位是有效的(1000与0001相比)。

所以我们可以使用 位掩码 来测试按键。

我写了一个小演示程序来帮助您可视化所有这些:

std::cout << "number of bytes in a short: " << sizeof(short) << std::endl;
short i = 0;
i = 1 << (sizeof(short)*8-1); // use bit shifting to set most significant bit
std::cout << "Initial value of i: " << i << std::endl;
std::cout << "Initial value of i as hex: " << std::hex << i << std::endl;
std::cout << "Is most significant bit set?\n";
short bitmask = 0x8000;
std::cout << std::boolalpha << ((bitmask & i) != 0) << std::endl;
std::cout << "Unsetting MSB\n";
i = 0x0000;
std::cout << "Is most significant bit set?\n";
std::cout << std::boolalpha << ((bitmask & i) != 0) << std::endl;

这个演示展示了如何对一个short应用位掩码来检查是否设置了最高位。 GetAsyncKeyState 可以让你检查自上次检查以来按键是否被按下。如果想要一个更简单的调用,请查看 GetKeyState

“GetAsyncKeyState”使用最高有效位来表示按键的当前状态:“如果该函数成功,返回值将指定自上次调用GetAsyncKeyState以来是否按下了该键,以及该键当前是处于弹起还是按下状态。” - Miles Budnek
@MilesBudnek:这里的“and”是逻辑与,我相信。因此,如果自上次调用以来未按下键,则无论键的状态如何,该函数始终会返回false。 - AndyG
2
不,我只是进行了一个快速测试。它在我按下键后返回0x8001,然后在我释放它之前返回0x8000。 - Miles Budnek
@MilesBudnek:非常感谢您的细致!我已经更新了帖子。希望您会发现它更加准确。 - AndyG
@Dacul:我以为你想手动按住键而不是切换它? - AndyG
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接