Chinaunix首页 | 论坛 | 博客
  • 博客访问: 801659
  • 博文数量: 330
  • 博客积分: 9641
  • 博客等级: 中将
  • 技术积分: 3181
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
文章分类

全部博文(330)

文章存档

2012年(17)

2011年(135)

2010年(85)

2009年(57)

2008年(36)

我的朋友

分类: LINUX

2010-09-25 21:16:39

  据说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 (< 4)
    {
        buf = rl_gets();
        printf("What you got is: %s\n", buf);
        i++;
    }
    free(buf);
    return 0;
}




参考资料:
有大师风采的--Linux串口编程:http://www.cppblog.com/amazon/archive/2010/01/28/106644.html
GNU Readline Library: 
阅读(763) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~