【问题标题】:How do I check if a Key is pressed on C++如何检查是否在 C++ 上按下了某个键
【发布时间】:2017-05-26 20:10:11
【问题描述】:

如何检查 Windows 上是否按下了某个键?

【问题讨论】:

  • 没有跨平台的方法可以做到这一点。请指定您要在哪个平台上开发。
  • 如果您使用的是 Windows,请考虑使用 API GetAsyncKeyState() 和 GetKeyState()
  • 欢迎来到 StackOverflow。您当前形式的问题不适合 Stack Overflow,无法在本网站范围内回答。请访问help center 并阅读how do I ask a good question 部分。
  • 没有可移植的方法来确定程序是否可以访问键盘(或者实际上是任何 I/O 设备)。
  • 用更多细节编辑了我的问题(即使很久以前)

标签: c++ keyboard key


【解决方案1】:

正如其他人所说,没有跨平台的方法可以做到这一点,但在 Windows 上你可以这样做:

下面的代码检查“A”键是否按下。

if(GetKeyState('A') & 0x8000/*Check if high-order bit is set (1 << 15)*/)
{
    // Do stuff
}

如果发生轮班或类似情况,您需要通过以下其中一项:https://msdn.microsoft.com/de-de/library/windows/desktop/dd375731(v=vs.85).aspx

if(GetKeyState(VK_SHIFT) & 0x8000)
{
    // Shift down
}

低位表示按键是否被切换。

SHORT keyState = GetKeyState(VK_CAPITAL/*(caps lock)*/);
bool isToggled = keyState & 1;
bool isDown = keyState & 0x8000;

哦,别忘了

#include <Windows.h>

【讨论】:

  • 在网上所有复杂和超级困难的答案中,这是一个可以使用的!
【解决方案2】:

免责声明:此答案是在编辑问题以将其范围限制为特定操作系统之前提供的

没有便携式功能可以检查是否按下了键,如果没有则继续。这始终取决于系统。

适用于 linux 和其他 posix 兼容系统的解决方案:

Here, for Morgan Mattews's code 以与任何 POSIX 兼容系统兼容的方式提供 kbhit() 功能。他使用了在 termios 级别停用缓冲的技巧。

windows 解决方案:

对于windows,微软提供_kbhit()

【讨论】:

    【解决方案3】:

    检查是否按下了某个键,如果是,则执行操作

    考虑一下'select()',如果这个(据说是 Posix)函数在你的操作系统上可用。

    'select()' 使用 3 组位,您可以使用提供的函数创建这些位(参见 man select、FD_SET 等)。您可能只需要创建输入位(现在)


    来自手册页:

    'select()' "允许程序监视多个文件描述符,等待一个或多个文件描述符为某种类型的 I/O 操作“准备好”(例如,可能的输入)。文件描述符是如果可以执行相应的 I/O 操作(例如,没有阻塞的 read(2)...),则认为已准备就绪"

    当 select 被调用时:

    a) 该函数查看集合中标识的每个 fd,如果该 fd 状态表明您可以做某事(可能是读,也可能是写),select 将返回并让您去做...'all you got要做的'是扫描位,找到设置位,并对与该位关联的 fd 采取行动。

    第一组(传递给 select)包含活动输入 fd(通常是设备)。您可能只需要这组中的 1 位。并且只有 1 个 fd(即来自键盘的输入)、1 位,这一切都非常简单。通过 select 的返回,您可以“做事”(也许,在您获取 char 之后)。

    b) 该函数还有一个超时,您可以通过它确定等待 fd 状态更改的时间。如果 fd 状态没有改变,超时将导致 'select()' 返回 0。(即没有键盘输入)您的代码此时也可以做一些事情,也许是输出。

    fyi - fd 通常是 0,1,2...记住 C 使用 0 作为 STDIN、1 和 STDOUT。


    简单的测试设置:我打开一个终端(与我的控制台分开),然后在该终端中键入 tty 命令以查找其 ID。响应通常类似于“/dev/pts/0”,或 3,或 17...

    然后我通过使用 open 得到一个 fd 在 'select()' 中使用:

    // flag options are: O_RDONLY, O_WRONLY, or O_RDWR
    int inFD = open( "/dev/pts/5", O_RDONLY ); 
    

    计算这个值很有用。

    这是一个需要考虑的 sn-p(来自 man select):

      fd_set rfds;
      struct timeval tv;
      int retval;
    
      /* Watch stdin (fd 0) to see when it has input. */
      FD_ZERO(&rfds);
      FD_SET(0, &rfds);
    
      /* Wait up to five seconds. */
      tv.tv_sec = 5;
      tv.tv_usec = 0;
    
      retval = select(1, &rfds, NULL, NULL, &tv);
      /* Don't rely on the value of tv now! */
    
      if (retval == -1)
          perror("select()");
      else if (retval)
          printf("Data is available now.\n");  // i.e. doStuff()
          /* FD_ISSET(0, &rfds) will be true. */
      else
          printf("No data within five seconds.\n"); // i.e. key not pressed
    

    【讨论】:

    • 我认为这个 Posix 函数是可移植的。例如,我在嵌入式系统的 vxWorks 和 Ubuntu Linux 上使用了“select()”。因此,尽管有其他说法,这可能是跨平台的。
    【解决方案4】:

    你说的是getchar函数吗?

    http://en.cppreference.com/w/c/io/getchar

    【讨论】:

    • 数据块,所以会按下一个键。
    猜你喜欢
    • 2018-05-02
    • 1970-01-01
    • 2016-03-27
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多