getch 在没有 initscr 的情况下无法工作

getch not working without initscr

我完成了 NCURSES 的 Documentation。我不明白如果我在没有 initscr 的情况下使用 getch 那么为什么这个程序不工作。有没有其他方法可以在不清除屏幕的情况下获取箭头键输入(initscr 做的)。

#include <ncurses.h>
#include <unistd.h>
int main()
{
    int ch;
    //initscr();
    //raw();
    //keypad(stdscr, TRUE);
    //noecho();

    while(1)
    {
        ch = getch();
        switch(ch)
        {
            case KEY_UP: 
                printw("\nUp Arrow");
                break;
            case KEY_DOWN: 
                printw("\nDown Arrow");
                break;
            case KEY_LEFT: 
                printw("\nLeft Arrow");
                break;
            case KEY_RIGHT: 
                printw("\nRight Arrow");
                break;
        }

        if(ch == KEY_UP)
            break;
    }
    //endwin();
}

getch 等同于 wgetch(stdscr)。它假定屏幕已经初始化。 ncurses(任何 curses 实现)必须做一些事情才能使 wgetch 可用:

  • 阅读终端说明
  • 初始化终端I/O模式
  • 分配一个屏幕来绘制。

最后一个是因为 wgetch 在读取之前对调用它的 window 执行了 wrefresh

您可以使用 newterm with filter to avoid clearing the screen, and doing line-oriented input. The filter program in ncurses-examples 演示如何执行此操作。

或者,您可以通过 termios 中的 tcsetattr 更改终端属性。如果您在 canonical mode(需要换行才能开始该过程)和 non-canonocal mode(按键绰绰有余)之间循环。

以下程序的工作方式如下 - 进程等待用户输入。如果按下向上箭头键,它会打印 'Arrow key pressed' 并退出。如果按下其他东西,它会等待用户按下 Enter 然后打印用户输入。打印输入后退出。

#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
  struct termios oldt, newt;
  char ch, command[20];
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  while(1)
  {
    ch = getchar();
    if (ch == '3')
    { printf("Arrow key\n"); ch=-1; break;}
    else if(ch == -1) // by default the function returns -1, as it is non blocking
    {
      continue;
    }
    else
    {
      break;
    }

  }
  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);
  if(ch != EOF)
  {
    ungetc(ch,stdin);ith
    putchar(ch);
    scanf("%s",command);
    printf("\n%s\n",command);

    return 1;
  }

  return 0;
}

我有一个没有 ncurses 的解决方案

您可以这样使用 simple-getch

t_key keys[] = {
  {"[A", K_UP},
  {"[B", K_DOWN},
  {"[D", K_LEFT},
  {"[C", K_RIGHT},
  {NULL, K_UNK},
};

int key;

ch_init();
while ((key = ch_get(keys)) != K_BACK)
  {
    printf("%d\n", key);
  }
ch_end();

keys 数组是将要使用的转义序列列表,(当您在终端中键入箭头键时,它将写入一个转义键,后跟多个字符以定义该键。)

此序列 may/will 在终端之间变化,您应该使用 termcap 正确设置此序列。