ncurses 是基于终端的十分强大的图形库。
Vim, screen, sl 等终端程序都用到了这个库(足以见其强大)。

安装

部分系统默认安装了 ncurses ,手动安装的方式是: sudo aptitude install ncurses-dev

使用的程序需要 #include <ncurses.h> 。
编译时需要添加 -lncurses 参数进行链接。

开始和结束

调用 initscr 初始化窗口,endwin 结束窗口。

#include<curses.h>

WINDOW *initscr(void);
int endwin(void);

输出

调用 initscr 后调用 endwin 前,printf, std::cout 等标准输出不会显示在屏幕上。
而输出到屏幕上需要 ncurses 提供的相应函数。

函数

int addch(const chtype char_to_add);   // 当前位置添加字符
int addstr(const char *string_to_add);    // 当前位置添加字符串

int printw(char *format, ...);   // 类似于 printf
int refresh(void);    // 强制刷新物理屏幕

int beep(void);   // 终端响铃
int flash(void);   // 屏幕闪烁

输入

调用 scanf, getchar, cin 等标准输入函数同样无效。

函数

int cbreak();   // 字符一键入,直接传给程序(不用按下回车)
int nocbreak();  // 关闭 cbreak

int echo(void); // 开启输入回显
int noecho(void); // 关闭输入回显

int getch(void); // 读入一个字符
int scanw(char *format, ...); // 类似于 scanf

int clear(void); // 清屏

输入函数通常是阻塞的,但是通过调用 nodelay(stdscr, TRUE); 可以关闭阻塞。
此时若输入函数未读取到内容会返回 ERR 。

光标

控制光标。
调用 initscr 后调用 endwin 前,输出终端控制符改变光标是无效的。

函数及示例

int move(int x, int y); // 将光标移动到 [x] 行 [y] 列,左上角为 0 行 0 列

int curs_set(int visiblility); // 参数为 0 表示隐藏光标,1 表示显示光标

int getyx(WINDOW* win, int &x, int &y); // 获取指定窗口光标位置,示例如下

void move_up() { // 将光标上移
    int x, y;
    getyx(stdscr, x, y); // stdscr 表示标准屏幕
    move(x - 1, y);
}

指定位置输出

在指定位置输出不必先 move 再 printw ,
ncurses 提供了 mv 函数前缀在指定位置输出。
例如 mvprintw(1, 2, "%d", 2) 在 1 行 2 列输出 3 。
类似的有 mvaddch, mvaddstr 等。

颜色

初始化

首先需要调用 has_color() 查看当前运行环境是否支持彩色。
调用 start_color() 初始化颜色,成功则返回 OK 。

bool has_colors(void);
int start_color(void);

成功后会初始化全局变量 COLORS 表示终端支持的颜色数量
还会有 COLOT_WHITE, COLOR_RED 等 8 个表示颜色的变量。

使用

例如希望打印白底黑字的信息:

void print(const char *info) {
    init_pair(1, COLOR_BLACK, COLOR_WHITE);
        // 的一个参数表示编号,后面两个分别表示字体和背景颜色
    attron(COLOR_PAIR(1));
        // attron 是一个设置函数,COLOR_PAIR 返回指定编号的颜色信息
    addstr(info);
    attroff(COLOR_PAIR(1));
        // attroff 关闭设置(若接下来需要用其他颜色可以不调用 attroff 而直接使用 attron 覆盖设置
}

错误示例

值得注意的是,必须保证 init_pair 的编号不与其他已初始化的编号重复
一个错误的调用如下:

const char *info = "ERROR CODE";
init_pair(1, COLOR_BLACK, COLOR_WHITE);
attron(COLOR_PAIR(1));
addstr(info); // 打印白底黑字
init_pair(1, COLOR_BLACK, COLOR_RED);
attron(COLOR_PAIR(1));
addstr(info); // 打印白底红字

上述代码的期望打印出白字和黑字两种不同的颜色,
但事实上只会打印出红色一种。
解决方案便是将白底红字的 pair 编号设为 2 。

窗口

ncurses 有窗口类 WINDOW 并提供了 stdscr 作为默认窗口。
有时一个窗口无法满足需要,此时需要自己新建窗口。

新建窗口

调用 newwin 来新建窗口。

// 从 ([x], [y]) 开始新建 [line] 行 [column] 列的窗口。
WINDOW *newwin(int line, int column, int x, int y);

新建的窗口

通用输出

addch, printw 等输出方式只输出到 stdscr 。
ncurses 提供了 w 前缀来输出到指定窗口。
例如 wprintw(win, "%d", 1) 在 [win] 窗口输出 1 。
但是自己新建的窗口与 stdscr 不同,
若想在屏幕上显示需要调用 wrefresh(win) 刷新窗口。

若想在窗口中指定位置输出,可以用 mvw 前缀函数。
例如 mvwprintw(win, 1, 2, "%d", 3) 在 [win] 窗口的 1 行 2 列( 相对位置 )输出 3 。

子窗口

调用 subwin 创建子窗口。

// 从 ([x], [y]) 开始新建 [line] 行 [column] 列属于 [parent] 的子窗口。
WINDOW *subwin(WINDOW *parent, int line, int column, int x, int y);

子窗口与普通窗口的区别在于它与其父窗口共用屏幕储存空间,
子窗口修改时父窗口会直接受到影响。
比如新建了 stdscr 的子窗口 win ,
那么输出到 win 后想显示在屏幕不调用 wrefresh 而是调用 touchwin(stdscr) 。
touchwin 用于标记一个窗口被修改。

销毁窗口

调用 delwin 销毁窗口。

int delwin(WINDOW *win); // 销毁 [win] 窗口

窗口销毁后其在屏幕上对应的内容不会改变。

离开

有时候可能需要离开 ncurses 回到行缓冲模式做些事情而且需要在之后回到 ncurses 。
例如 Vim 里面输入 :!ls 就会退出 ncurses 运行 ls 命令,并在用户敲下回车后回到 ncurses。

调用 def_prog_mode 暂存,调用 reset_prog_mode 恢复。

示例

int main() {
    initscr();
    printw("Hello World !!!\n");
    getch(); // 等待用户输入
    def_prog_mode(); // 存储当前tty 模式
    endwin(); // 退出 ncurses 模式
    system("sh"); // 返回普通的行缓冲模式
    reset_prog_mode(); // 返回到 def_prog_mode() 存储的 tty 模式
    refresh(); // 刷新屏幕(必须!)
    getch(); // 等待用户输入
    endwin(); // 退出 ncurses 模式
    return 0;
}

输出中文等非 ASCII 字符

事实上 ncurses 并不支持直接输出中文,
这意味着调用 printw(“中文”) 会是一堆乱码。
解决方案如下:

安装库

这需要另一个库。
通过 sudo aptitude install libncurses5 libncursesw5 libncursesw5-dbg libncursesw5-dev 安装

头文件

一定是 #include <ncurses.h> 而不是 #include <curses.h>
另外在 main.cpp #include <locale.h>

调用

在调用 initscr() 之前 调用 setlocale(LC_ALL, “”) 。

编译

-lncurses 参数改为 -lncursesw

分类: 杂项

4 条评论

kiosk3 scr888.yahoo · 2019年3月9日 上午9:11

我错了,我再也不敢发广告了,在此表示抱歉。

scr888 rm10 · 2019年6月25日 下午10:23

Pai Gow dwells of a bank having one woodpile. The Kasharoo slts game from Quicksilver Games is really
a 5 reel and 30 pay line game. The odds of winning on such slots are potentially more ass fewer players enteer
such turnament situation. http://www.casinogamefactory.com/enjoy-gambling-by-keeping-the-fun-element-in-it/

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: