据说Windows下后hook函数可以捕捉,还看到同学拿VB写的,都很简单。在ChinaUnix论坛上发帖网,终于求助到tcsetattr和readline两种方法。
1.tcsetattr()
一组控制terminal函数中的一个,在Linux串口编程中用到。
一个简单的把EOF从Ctrl+D 改变成Ctrl+G 的程序:
int cheof()
{
int ch, err;
struct termios termt;
if ( -1 == tcgetattr(STDIN_FILENO, &termt) )
{
perror("Cannot get standard input description");
return 1;
}
/* 0x07 represent Ctrl+G */
termt.c_cc[VEOF] = (cc_t)0x07;
err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &termt);
if (err == -1 && err == EINTR)
{
perror("Failed to change EOF character");
return 1;
}
return ch;
}
|
由简入繁,下面是捕捉方向键,程序想法来自:!5659510D27949B4!372.entry
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
int getattr(struct termios *oldt)
{
if ( -1 == tcgetattr(STDIN_FILENO, oldt) )
{
perror("Cannot get standard input description");
return 1;
}
return 0;
}
int setattr(struct termios newt)
{
newt.c_lflag &= ~(ICANON | ECHO | ISIG);
newt.c_cc[VTIME] = 0;
newt.c_cc[VMIN] = 1;
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
return 0;
}
int resetattr(struct termios *oldt)
{
tcsetattr(STDIN_FILENO, TCSANOW, oldt);
return 0;
}
int getkey()
{
char buf[3];
ssize_t bytes_read;
switch ( bytes_read = read(STDIN_FILENO, &buf, 3) )
{
case -1:
perror("Error");
return -1;
case 1:
printf("Entered character: %c, %d\n", buf[0], buf[0]);
return buf[0];
case 3:
switch(buf[2])
{
case 'A':
printf("Press up\n");
return 0xe048;
case 'B':
printf("Press down\n");
return 0xe050;
case 'C':
printf("Press right\n");
return 0xe04d;
case 'D':
printf("Press left\n");
return 0xe04b;
}
}
return 0;
}
|
int main()
{ int get;char ch;
struct termios oldt;
getattr(&oldt);
setattr(oldt);
while (1)
{
get = getkey();
if (get == 27)
break;
}
/*
do {
ch = getchar();
//switch ( ret = read(STDIN_FILENO, &ch, 1) )
//{
// case -1:
// perror("Error");
// exit(3);
// case 0:
// perror("0 read");
// exit(4);
//}
printf("Entered character: %c, %d\n", ch, ch);
} while (ch != '0');
*/
resetattr(&oldt);
return 0;
}
|
这里的问题显而易见,只能捕捉上下左右,无法捕捉一个单词,比如我要敲入fiber,就会产生每个字母输出一行的状况。
具体解决方法还不明。
2.readline库
readline库正是Linux下bash用到的一个too big and too slow的库。包括Tab补全、上键history、Ctrl+u特殊快捷键等等的众多特性。
下面是来自GNU文档里的不错示例的修改,使用起来十分简单:
/* linking library: -lreadline -ltermcap */ #include <stdio.h> #include <stdlib.h> #include <readline/readline.h> #include <readline/history.h>
/* A static variable for holding the line. */ static char *line_read = (char *)NULL;
/* Read a string, and return a pointer to it. Returns NULL on EOF. */ char *rl_gets () { /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) { free (line_read); line_read = (char *)NULL; }
/* Get a line from the user. */ line_read = readline ("Enter:");
/* If the line has any text in it, save it on the history. */ if (line_read && *line_read) add_history (line_read);
return (line_read); }
int main() { /* To disable the default TAB behavior. */ rl_bind_key('\t', rl_insert);
char *buf; int i = 1; while (i < 4) { buf = rl_gets(); printf("What you got is: %s\n", buf); i++; } free(buf); return 0; }
|
参考资料:
GNU Readline Library:
阅读(2083) | 评论(0) | 转发(0) |