如何在不清除屏幕的情况下使用curses库中的getch函数?

14

我正在学习C语言编程,希望在代码正在运行时能够输入字符而不必按下回车键。我的程序可以正常工作,但是当我调用initscr()时,屏幕被清除了,即使我调用了filter()filter的文档建议它应该禁用清除 - 但对我来说并非如此。

#include <stdio.h>
#include <curses.h>
#include <term.h>

int main(void) {

    int ch;

    filter();
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    while((ch = getch()) != EOF);

    endwin();

    return 0;
}
为什么上面的代码仍然清除屏幕,如何修复它? 我正在使用 Debian Lenny(stable)和 gnome-terminal。

对于PDCurses,您可以将环境变量PDC_PRESERVE_SCREEN或PDC_RESTORE_SCREEN设置为任何值:来自文件HISTORY: - Brandin
PDC_PRESERVE_SCREEN 如果设置了此环境变量,则PDCurses在启动时不会将屏幕清除为默认的白色背景黑色字体。这允许您在现有屏幕背景上叠加窗口。PDC_RESTORE_SCREEN 如果设置了此环境变量,则PDCurses将在启动PDCurses(initscr())和调用endwin()时,复制屏幕内容,并在结束时还原屏幕。 - Brandin
4个回答

4

在curses应用程序中,您可能会看到屏幕被清除,原因如下:

  • 您的程序调用initscr(它会清除屏幕)或没有先调用filternewterm,或者
  • 终端初始化清除了屏幕(或通过切换到替代屏幕使其看起来被清除)。

在后一种情况下,可以通过将enter_ca_modeexit_ca_mode指针重置为NULL(即像dialog中所做的那样)来禁用ncurses中的备用屏幕功能。更好的选择是选择一个可以满足您需要的终端描述。

进一步阅读:


2

在mike.dld的回答基础上,这对我在MacOS X 10.6.6 (GCC 4.5.2)上使用系统curses库有效 - 无需清除屏幕。我添加了记录键入字符(记录到文件“x”中)和输入CONTROL-D并停止程序的能力,而不是强制用户中断。

#include <stdio.h>
#include <curses.h>
#include <term.h>

#define CONTROL(x)  ((x) & 0x1F)

int main(void)
{
    FILE *fp = fopen("x", "w");
    if (fp == 0)
        return(-1);
    SCREEN *s = newterm(NULL, stdin, stdout);
    if (s == 0)
        return(-1);
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    int ch;
    while ((ch = getch()) != EOF && ch != CONTROL('d'))
        fprintf(fp, "%d\n", ch);

    endwin();

    return 0;
}

4
这对我来说确实清空了屏幕(所以它不起作用)。 - nh2
@nh2:这可能取决于您的终端类型和使用的curses条目。 - Jonathan Leffler

1
使用newterm()替代initscr(),然后你就应该没问题了。如果你遵循这个建议,别忘了调用delscreen()

嗨,感谢您的回复,我已经尝试了您所说的方法,但功能仍然相同 - 屏幕再次被清除。我使用的是FILE *fild_id = fopen("/dev/tty", "r+"); SCREEN *termref = newterm(NULL, file_id, file_id);代替initscr(),并使用delscreen(termref)代替endwin() - Chris R
很奇怪,当我使用newterm(NULL, stdin, stdout)代替initscr()时,它并没有清除我的屏幕。 - mike.dld
7
Mike,它不能清除你的屏幕的唯一原因是你反转了newterm()的参数。它需要stdout和stdin,而不是stdin和stdout。我敢打赌在你的测试程序运行后,你的输入被搞砸了吧?没有回显,也许?如果你使用正确的newterm()参数顺序,它确实会清除屏幕。你的答案是错误的。 - nick black
1
为什么不删除这个答案? - Ted Lyngmo
1
我完全赞成,但似乎在答案被接受的情况下无法删除@TedLyngmo。对此的任何帮助都是受欢迎的。 - mike.dld
@mike.dld 我明白了。我现在也记得发生过这种情况。好的,问题解决了。 :-) - Ted Lyngmo

1
基本上,curses 旨在接管屏幕(或窗口,在窗口终端的情况下)。你无法真正将 curses 与 stdio 混合使用,也无法仅使用 curses 输入或输出内容而不影响屏幕的其余部分。有一些部分性的解决方法,但你永远无法使它按照你想要的方式工作。抱歉。
我建议您要么重新编写程序以始终使用 curses,要么调查诸如 readline 等替代方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接