Linuxでユーザーにプロンプトを表示せずにCでキーボードイベントを検出する方法はありますか?つまり、実行中のプログラムは、いずれかのキーを押すことで終了するはずです。 誰でもこれを手伝ってもらえますか?ユーザにプロンプトを表示せずにLinux C GUIプログラムでキー押下を検出するにはどうすればよいですか?
答えて
これをグラフィカルアプリケーションで実行したい場合は、ライブラリを使用してこれを行う必要があります。
このような簡単な作業は、どのようなライブラリ(Xlibのような低レベルのものさえ)でも簡単に行うことができます。
キーボードイベントを処理する方法を示すチュートリアルを探してみてください。
ANSI Cを使用する方法はありません。ncurses libを見てください。
Hmm。 termiosコード、まっすぐなC、およびいくつかのunix呼び出しを参照してください。 –
はこちら/usr/src/bin/stty/key.c
からのコードです:
f_cbreak(struct info *ip)
{
if (ip->off)
f_sane(ip);
else {
ip->t.c_iflag |= BRKINT|IXON|IMAXBEL;
ip->t.c_oflag |= OPOST;
ip->t.c_lflag |= ISIG|IEXTEN;
ip->t.c_lflag &= ~ICANON;
ip->set = 1;
}
}
を最低でも、あなたはあなたのselect(2)
システムコールの前にICANON
モードから抜け出すために持っているか、あなたのFIONREAD ioctl
が動作します。
私はこの方法でCBREAKとECHOモードをクリアする20歳の古いperl4プログラムを持っています。これは、cursesライブラリに頼ることなく呪いのものをやっている:
sub BSD_cbreak {
local($on) = shift;
local(@sb);
local($sgttyb);
# global $sbttyb_t
$sgttyb_t = &sgttyb'typedef() unless defined $sgttyb_t;
# native BSD stuff by author (tsc)
ioctl(TTY,&TIOCGETP,$sgttyb)
|| die "Can't ioctl TIOCGETP: $!";
@sb = unpack($sgttyb_t,$sgttyb);
if ($on) {
$sb[&sgttyb'sg_flags] |= &CBREAK;
$sb[&sgttyb'sg_flags] &= ~&ECHO;
} else {
$sb[&sgttyb'sg_flags] &= ~&CBREAK;
$sb[&sgttyb'sg_flags] |= &ECHO;
}
$sgttyb = pack($sgttyb_t,@sb);
ioctl(TTY,&TIOCSETN,$sgttyb)
|| die "Can't ioctl TIOCSETN: $!";
}
sub SYSV_cbreak {
# SysV code contributed by Jeff Okamoto <[email protected]>
local($on) = shift;
local($termio,@termio);
# global termio_t ???
$termio_t = &termio'typedef() unless defined $termio_t;
ioctl(TTY,&TCGETA,$termio)
|| die "Can't ioctl TCGETA: $!";
@termio = unpack($termio_t, $termio);
if ($on) {
$termio[&termio'c_lflag] &= ~(&ECHO | &ICANON);
$termio[&termio'c_cc + &VMIN] = 1;
$termio[&termio'c_cc + &VTIME] = 1;
} else {
$termio[&termio'c_lflag] |= (&ECHO | &ICANON);
# In HP-UX, it appears that turning ECHO and ICANON back on is
# sufficient to re-enable cooked mode. Therefore I'm not bothering
# to reset VMIN and VTIME (VEOF and VEOL above). This might be a
# problem on other SysV variants.
}
$termio = pack($termio_t, @termio);
ioctl(TTY, &TCSETA, $termio)
|| die "Can't ioctl TCSETA: $!";
}
sub POSIX_cbreak {
local($on) = shift;
local(@termios, $termios, $bitmask);
# "file statics" for package cbreak:
# $savebits, $save_vtime, $save_vmin, $is_on
$termios_t = &termios'typedef() unless defined $termios_t;
$termios = pack($termios_t,()); # for Sun SysVr4, which dies w/o this
ioctl(TTY,&$GETIOCTL,$termios)
|| die "Can't ioctl GETIOCTL ($GETIOCTL): $!";
@termios = unpack($termios_t,$termios);
$bitmask = &ICANON | &IEXTEN | &ECHO;
if ($on && $cbreak'ison == 0) {
$cbreak'ison = 1;
$cbreak'savebits = $termios[&termios'c_lflag] & $bitmask;
$termios[&termios'c_lflag] &= ~$bitmask;
$cbreak'save_vtime = $termios[&termios'c_cc + &VTIME];
$termios[&termios'c_cc + &VTIME] = 0;
$cbreak'save_vmin = $termios[&termios'c_cc + &VMIN];
$termios[&termios'c_cc + &VMIN] = 1;
} elsif (!$on && $cbreak'ison == 1) {
$cbreak'ison = 0;
$termios[&termios'c_lflag] |= $cbreak'savebits;
$termios[&termios'c_cc + &VTIME] = $cbreak'save_vtime;
$termios[&termios'c_cc + &VMIN] = $cbreak'save_vmin;
} else {
return 1;
}
$termios = pack($termios_t,@termios);
ioctl(TTY,&$SETIOCTL,$termios)
|| die "Can't ioctl SETIOCTL ($SETIOCTL): $!";
}
sub DUMB_cbreak {
local($on) = shift;
if ($on) {
system("stty cbreak -echo");
} else {
system("stty -cbreak echo");
}
}
そして、それは他の場所でPOSIXのために、元のCに
($GETIOCTL, $SETIOCTL) = (TIOCGETA, TIOCSETA);
RE-翻訳は、読者のための運動として残っているという20年前の私が元々どこから来たのかを覚えていないからです。 :(あなたが正確にどのように多くのバイトを発見するFIONREAD ioctl
を行うselect
年代は、その記述子が準備ができていることをマスクリターンを読んで、あなたがtty上ICANONモードの外出たら、今あなたのselect(2)
システムコールが再び正常に動作
は、今ではそれはもはや必要ではないはずですが、それは、あなたが好ましくO_NONBLOCK
ディスクリプタに、ちょうどその多くのバイトをread(2)
システムコールを行うことができました。そのファイルディスクリプタであなたを待っている。
フム、ここ予感です/usr/src/usr.bin/vi/cl/README.signal
の注記:
Run in cbreak mode. There are two problems in this area. First, the
current curses implementations (both System V and Berkeley) don't give
you clean cbreak modes. For example, the IEXTEN bit is left on, turning
on DISCARD and LNEXT. To clarify, what vi WANTS is 8-bit clean, with
the exception that flow control and signals are turned on, and curses
cbreak mode doesn't give you this.
We can either set raw mode and twiddle the tty, or cbreak mode and
twiddle the tty. I chose to use raw mode, on the grounds that raw
mode is better defined and I'm less likely to be surprised by a curses
implementation down the road. The twiddling consists of setting ISIG,
IXON/IXOFF, and disabling some of the interrupt characters (see the
comments in cl_init.c). This is all found in historic System V (SVID
3) and POSIX 1003.1-1992, so it should be fairly portable.
カーネル以外の部分に\b(TIOC[SG]ET[NP]|TC[SG]ET[SA]|tc[sg]etattr)\b
の再帰的なgrep
を/usr/src/
とすると、使用できるものが見つかるはずです。たとえば:
% grep -Pr '\b(TIOC[SG]ET[NP]|TC[SG]ET[SA]|tc[sg]etattr)\b' /usr/src/{{s,}bin,usr.{s,}bin,etc,gnu}
私はダウンraw_mode()
機能では、/usr/src/usr.bin/less/screen.c
になります。 ifdef
で悩んでいますが、それは移植性を追求していますが、これはあなたがしたいことのための最もクリーンなコードのように見えます。 GNUに潜んでいるものもあります。
OH MY、/usr/src/gnu/usr.bin/perl/h2pl/cbreak.pl
をご覧ください!それは私が上に投稿した私の古いコードでなければなりません。興味深いことに、それは世界のすべてのsrcシステムに波及しています。それはがから20年古いですから、恐ろしいです。まあ、若い自分のエコーを見るのは変です。 20年前からこのようなことを覚えているのは本当に難しい。termio
またはtermios
可用性を推測しようとしているifdef
Sの束に
#define tcgetattr(fd, arg) ioctl(fd, TCGETA, arg)
:
は私も/usr/src/lib/libcurses/term.h
にこの行を参照してください。
これで十分です。
termiosを使用して端末設定を変更する必要があります。 Stevens & Rago 2nd Ed「UNIX環境での高度なプログラミング」を参照してください。なぜtcsetattr()がすべての端末特性を設定せずにsuccessfulyを返すことができ、なぜtcsetattr()の呼び出しが冗長であるかがわかります。
これは、UNIXでANSI Cである:
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
int checktty(struct termios *p, int term_fd)
{
struct termios ck;
return (
tcgetattr(term_fd, &ck) == 0 &&
(p->c_lflag == ck.c_lflag) &&
(p->c_cc[VMIN] == ck.c_cc[VMIN]) &&
(p->c_cc[VTIME] == ck.c_cc[VMIN])
);
}
int
keypress(int term_fd)
{
unsigned char ch;
int retval=read(term_fd, &ch, sizeof ch);
return retval;
}
int /* TCSAFLUSH acts like fflush for stdin */
flush_term(int term_fd, struct termios *p)
{
struct termios newterm;
errno=0;
tcgetattr(term_fd, p); /* get current stty settings*/
newterm = *p;
newterm.c_lflag &= ~(ECHO | ICANON);
newterm.c_cc[VMIN] = 0;
newterm.c_cc[VTIME] = 0;
return(
tcgetattr(term_fd, p) == 0 &&
tcsetattr(term_fd, TCSAFLUSH, &newterm) == 0 &&
checktty(&newterm, term_fd) != 0
);
}
void
term_error(void)
{
fprintf(stderr, "unable to set terminal characteristics\n");
perror("");
exit(1);
}
void
wait_and_exit(void)
{
struct timespec tsp={0,500}; /* sleep 500 usec (or likely more) */
struct termios attr;
struct termios *p=&attr;
int keepon=0;
int term_fd=fileno(stdin);
fprintf(stdout, "press any key to continue:");
fflush(stdout);
if(!flush_term(term_fd, p))
term_error();
for(keepon=1; keepon;)
{
nanosleep(&tsp, NULL);
switch(keypress(term_fd))
{
case 0:
default:
break;
case -1:
fprintf(stdout, "Read error %s", strerror(errno));
exit(1);
break;
case 1: /* time to quit */
keepon=0;
fprintf(stdout, "\n");
break;
}
}
if(tcsetattr(term_fd, TCSADRAIN, p) == -1 &&
tcsetattr(term_fd, TCSADRAIN, p) == -1)
term_error();
exit(0);
}
int main()
{
wait_and_exit();
return 0; /* never reached */
}
にnanosleepコールがシステムリソースをgobblingからコードを防ぐためにそこにあります。 nice()を呼び出し、nanosleep()を使わないでください。すべてこれは座ってキーストロークを待ってから終了します。
OS X 10.6で動作することを確認できます。 – febeling
- 1. ユーザにプロンプトを表示するバッチコピースクリプト
- 2. Python:特定のキーを検出してユーザにプロンプトを表示
- 3. pyodbc.connectにプロンプトを表示するにはどうすればよいですか?
- 4. Xamarinフォームでブルートゥースを有効にするようにプロンプトを表示する
- 5. jlineは最下部にプロンプトを表示します
- 6. WPFでAltキーを押さずにAccessKeyを表示するにはどうすればいいですか?
- 7. GUIではなく、Javaコンソールで矢印キーを検出するにはどうすればよいですか?
- 8. ユーザにプロンプトを出すノードの実行コマンド
- 9. javascriptのキー押下でキーを無効にするにはどうすればよいですか?
- 10. Sublime Text 2を終了する前にプロンプトを表示させるにはどうすればよいですか?
- 11. ユーザーにプロンプトを表示せずにgoogle apiでオフラインアクセスを取得するには
- 12. Windowsからデュアルブート(特にLinux)をプログラムで検出するにはどうすればよいですか?
- 13. Linuxでファイルアクセスを検出するにはどうすればよいですか?
- 14. Linux C++:テキストアプリケーション出力をstdoutの外に表示するにはどうすればよいですか?
- 15. SearchTaskにプロンプトが表示されるのはなぜですか?
- 16. Linuxでスタックトレースを表示するにはどうすればよいですか?
- 17. ボットフレームワークのボタンではなく、カルーセルでユーザにプロンプトを表示できますか?
- 18. テンプレートをレイアウトテンプレート内に表示せずに表示するにはどうすればよいですか?
- 19. APIを使用せずにプログラムで検索を実行するにはどうすればよいですか?
- 20. プログラムの出力を表示するダイアログボックスを表示するにはどうすればよいですか?
- 21. C/C++プログラムから__strlen_sse2を呼び出すにはどうすればよいですか? [Linux]
- 22. Visual Studio 2015のcmdコンソールではなく、GUI出力ウィンドウでC++プログラムの出力を表示するにはどうすればよいですか?
- 23. プログラムでレイヤーパネルを表示するにはどうすればよいですか?
- 24. Linux | Cでのシェルの実装|リダイレクトされたファイルにプロンプトが表示される
- 25. insertを押すとフォームを表示/非表示にするにはどうすればよいですか?
- 26. OpenID Connectでサインインしているときにプロンプトを表示する
- 27. Racket Webアプリケーションのキー押下をどのように検出しますか?
- 28. ボタンを押さずにこのコンテンツを表示するにはどうすればいいですか?
- 29. C++でランタイムエラーを検出するにはどうすればよいですか?
- 30. Visual Studioの前にキーの押下を処理するにはどうすればよいですか?
これは端末またはGUIプログラムで行いますか?あるいは、SDLを使用しているような、フルスクリーンのフレームバッファのようなプログラムでしょうか?または、他の何か? –
私はスクリーンセーバーのようなGUIプログラムのためにこれを望みます。私はいくつかのキーを押すとすぐに、アプリケーションは終了する必要があります。 –
次に、次の質問があります:どのGUIフレームワークを使用していますか? – casablanca