【问题标题】:How do I use getch from curses without clearing the screen?如何在不清除屏幕的情况下从诅咒中使用 getch?
【发布时间】:2011-06-13 21:51:59
【问题描述】:

我正在学习用 C 编程,并希望能够在我的代码运行时在终端中键入字符而无需按 return。我的程序可以运行,但是当我调用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(稳定版)和 gnome-terminal。

【问题讨论】:

  • 对于 PDCurses,您可以将环境变量 PDC_PRESERVE_SCREEN 或 PDC_RESTORE_SCREEN 设置为任何值:来自文件 HISTORY:
  • PDC_PRESERVE_SCREEN 如果设置了此环境变量,PDCurses 将不会在启动时将屏幕清除为默认的黑底白字。这允许您在现有屏幕背景的顶部覆盖一个窗口。 PDC_RESTORE_SCREEN 如果设置了此环境变量,PDCurses 将在 PDCurses 启动时获取屏幕内容的副本; initscr(),当调用 endwin() 时,屏幕将恢复。

标签: c ncurses curses


【解决方案1】:

由于以下原因之一,您会在 curses 应用程序中看到您的屏幕被清除:

  • 您的程序调用initscr(清除屏幕)或newterm,而无需先调用filter,或
  • 终端初始化会清除屏幕(或通过切换到备用屏幕使其看起来很清晰)。

在后一种情况下,您可以通过将 enter_ca_modeexit_ca_mode 指针重置为 NULL as done in dialog 来抑制 ncurses 中的备用屏幕功能。更好的是,选择一个符合您要求的终端描述。

进一步阅读:

【讨论】:

    【解决方案2】:

    通过 mike.dld 扩展答案,这适用于带有系统诅咒库的 MacOS X 10.6.6 (GCC 4.5.2) - 无需清除屏幕。我添加了记录输入字符的功能(记录到文件“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;
    }
    

    【讨论】:

    • 这确实为我清除了屏幕(所以它不起作用)。
    • @nh2:这可能取决于您的终端类型和您正在使用的 curses 条目。
    【解决方案3】:

    基本上,curses 旨在接管屏幕(或窗口,在窗口终端的情况下)。您不能真正将 curses 与 stdio 混合使用,并且您不能真正使用 curses 来输入或输出某些内容而不会弄乱屏幕的其余部分。有部分解决方法,但你永远无法真正让它按照你想要的方式工作。对不起。

    我建议要么重写你的程序以在整个过程中使用诅咒,要么研究像 readline 这样的替代方案。

    【讨论】:

      【解决方案4】:

      使用newterm() 而不是initscr(),那你应该没问题。如果您遵循此建议,请不要忘记 delscreen()

      【讨论】:

      • 您好,谢谢您的回复,您说的我已经试过了,功能还是一样的——屏幕又被清空了。代替initscr() 我有FILE *fild_id = fopen("/dev/tty", "r+"); SCREEN *termref = newterm(NULL, file_id, file_id); 而不是endwin() 我有delscreen(termref)
      • 奇怪,但当我使用它而不是 initscr() 时,它并没有清除我的屏幕。我把它称为newterm(NULL, stdin, stdout)
      • 迈克,它没有清除屏幕的唯一原因是您将参数反转为 newterm()。它需要标准输出,标准输入,而不是标准输入,标准输出。我敢打赌,在您的测试程序运行后,您的输入是混乱的?不回声,也许?如果您对 newterm() 使用正确的参数顺序,它确实会清除屏幕。你的答案是错误的。
      • 为什么不删除这个答案?
      • 我完全赞成,但在@TedLyngmo 接受时,我似乎无法删除答案。欢迎提供任何帮助。
      猜你喜欢
      • 2013-11-13
      • 2014-05-25
      • 2014-09-05
      • 2022-10-07
      • 1970-01-01
      • 2014-09-17
      • 2018-02-27
      • 1970-01-01
      • 2012-01-04
      相关资源
      最近更新 更多