如何检查是否在 C++ 上按下了键

How do I check if a Key is pressed on C++

提问人:snivy9014 提问时间:1/12/2017 最后编辑:snivy9014 更新时间:7/19/2021 访问量:197490

问:

我怎么可能检查是否在 Windows 上按下了键?

C++ 键盘

评论

8赞 Rakete1111 1/12/2017
没有跨平台的方法可以做到这一点。请指定您要在哪个平台上开发。
1赞 Raindrop7 1/12/2017
如果您使用的是 Windows,请考虑使用 API 和GetAsyncKeyState()GetKeyState()
1赞 Captain Obvlious 1/12/2017
欢迎来到 StackOverflow。您的问题目前的形式不适合 Stack Overflow,无法在本站点范围内回答。请访问帮助中心并阅读“如何提出好问题”部分。
0赞 Toby Speight 1/12/2017
没有可移植的方法来确定程序是否有权访问键盘(或者实际上,任何 I/O 设备)。
0赞 snivy9014 9/24/2017
用更多细节编辑了我的问题(即使很久以前)

答:

-4赞 Jeandey Boris 1/12/2017 #1

你说的是功能吗?getchar

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

评论

1赞 user4581301 1/12/2017
数据块,因此将按下一个键。
0赞 Lixt 12/13/2022
我不推荐它。它要求输入,而不是检查是否在运行时按下了某个键(不阻塞代码)
8赞 Christophe 1/12/2017 #2

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

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

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

在这里,对于 Morgan Mattews 的代码,它以与任何 POSIX 兼容系统兼容的方式提供功能。他使用了在 termios 级别停用缓冲的技巧。kbhit()

Windows解决方案:

对于 Windows,Microsoft 提供 _kbhit()

63赞 Frank S. 1/12/2017 #3

正如其他人所提到的,没有跨平台的方法可以做到这一点,但在 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>

评论

4赞 Anders Cedronius 5/8/2018
在网络上所有复杂且困难的答案中,这是要使用的答案!
3赞 2785528 1/12/2017 #4

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

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

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


从手册页:

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

调用 select 时:

a) 该函数查看集合中标识的每个 FD,如果该 FD 状态表明您可以执行某些操作(也许是读取,也许是写入),则选择将返回并让您执行该操作......“您所要做的就是扫描位,找到设置的位,然后对与该位关联的 FD 执行操作。

第一组(传入 select)包含活动输入 fd(通常是设备)。您可能只需要此集合中的 1 位。只需 1 个 fd(即来自键盘的输入),1 位,这一切都非常简单。通过从 select 返回,您可以“做一些事情”(也许,在您获取字符之后)。

b) 该函数还具有超时功能,您可以使用它来确定等待 FD 状态更改的时间。如果 fd 状态没有改变,超时将导致 'select()' 返回 0。(即无键盘输入)此时,您的代码也可以执行某些操作,例如输出。

仅供参考 - FD 通常为 0,1,2...记住 C 使用 0 作为 STDIN、1 和 STDOUT。


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

然后我通过使用 open 在“select()”中使用一个 fd:

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

确定此值很有用。

这是一个需要考虑的片段(来自 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

评论

0赞 2785528 1/12/2017
我认为这个 Posix 函数是可移植的。例如,我在嵌入式系统的vxWorks和Ubuntu Linux上使用了'select()'。因此,尽管有其他说法,但也许这是跨平台的。