实现在C键preSS事件 [英] Implementing a KeyPress Event in C

查看:161
本文介绍了实现在C键preSS事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有类似下面的一个无限循环,而这个循环中,我要不断地检查键盘,看看是否退出键(ESC)已经pssed与否$ P $。如果它是pssed $ P $,则该循环应该被打破。我怎么可以在C这样做吗? (我用gcc,做访问的pthreads以及在此情况下,必须通过线程来完成)

 而(1){
        //做一点事
        //检查ESC键
 }


解决方案

这在很大程度上取决于系统。在Unix / Linux系统中,默认的终端处理程序收集线,只有当全系列可通知程序(在<大骨节病>输入被击中。)如果你不是立即需要的按键,你需要把终端成非规范方式:

 的#include&LT; termios.h&GT;结构termios的信息;
tcgetattr(0,&放大器;信息); / *获取当前终端attirbutes; 0是标准输入文件描述符* /
info.c_lflag&安培; =〜ICANON; / *禁用标准模式下* /
info.c_cc [VMIN] = 1; / *等到至少有一个按键可用* /
info.c_cc [VTIME] = 0; / *无超时* /
tcsetattr(0,TCSANOW,&放大器;信息); / *立即设置* /

一旦你这样做,你可以使用标准输入读取的任何电话,他们将返回键,而无需等待该行的末尾。除了可以设置 c_cc中[VMIN] = 0 造成当你从标准输入读取它不会等待按键都没有。

不过,如果你读与标准输入输出的文件的相关电话(getchar函数等),设置VMIN = 0将使其觉得你已经达到EOF每当有没有可用的钥匙,所以你必须调用标准输入的clearerr 之后,恰好尝试读取多个字符。您可以使用像一个循环:

  INT CH;
而((CH =的getchar())!= 27 / * ASCII ESC * /){
    如果(CH℃,){
        如果(FERROR(标准输入)){/ *有一个错误... * /}
        的clearerr(标准输入);
        / *做其他的东西* /
    }其他{
        / *比ESC键一些其他被击中,做点什么? * /
    }
}

大功告成之后,你可能要确保将终端设置回标准模式下,以免其它程序(如您的shell)感到困惑:

  tcgetattr(0,&安培;信息);
info.c_lflag | = ICANON;
tcsetattr(0,TCSANOW,&放大器;信息);

还有其他事情可以做tcsetattr - 看到那么手册页的详细信息。这可能足以满足您的目的一方面是设置一个替代EOL字符。

I have a infinite loop like the following one, and within this loop, I want to continuously check the keyboard to see if the escape key (ESC) has been pressed or not. If it is pressed, then the loop should be broken. How I can do this in C? (I am using gcc, and do access to pthreads as well in case this must be done via threads)

 while(1){
        //do something
        //check for the ESC key
 }

解决方案

This is heavily system dependent. In Unix/Linux systems, the default terminal handler gathers lines and only notifies the program when a full line is available (after Enter is hit.) If you instead want keystrokes immediately, you need to put the terminal into non-canonical mode:

#include <termios.h>

struct termios info;
tcgetattr(0, &info);          /* get current terminal attirbutes; 0 is the file descriptor for stdin */
info.c_lflag &= ~ICANON;      /* disable canonical mode */
info.c_cc[VMIN] = 1;          /* wait until at least one keystroke available */
info.c_cc[VTIME] = 0;         /* no timeout */
tcsetattr(0, TCSANOW, &info); /* set immediately */

Once you've done that, you can use any calls that read from stdin and they will return keys without waiting for the end of the line. You can in addition set c_cc[VMIN] = 0 to cause it to not wait for keystrokes at all when you read from stdin.

If, however, you're reading stdin with stdio FILE related calls (getchar, etc), setting VMIN = 0 will make it think you've reached EOF whenever there are no keys available, so you'll have to call clearerr after that happens to try to read more characters. You can use a loop like:

int ch;
while((ch = getchar()) != 27 /* ascii ESC */) {
    if (ch < 0) {
        if (ferror(stdin)) { /* there was an error... */ }
        clearerr(stdin);
        /* do other stuff */
    } else {
        /* some key OTHER than ESC was hit, do something about it? */
    }
}

After you're done, you probably want to be sure to set the terminal back into canonical mode, lest other programs (such as your shell) get confused:

tcgetattr(0, &info);
info.c_lflag |= ICANON;
tcsetattr(0, TCSANOW, &info);

There are also other things you can do with tcsetattr -- see then manual page for details. One thing that might suffice for your purposes is setting an alternative EOL character.

这篇关于实现在C键preSS事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆