ncurses是一个管理应用程序在字符终端显示的函数库。它提供了移动光标,建立窗口,产生颜色,处理鼠标操作等功能。
ncurses提供的是字符用户界面,而非图形用户界面。
在Ubuntu下执行如下命令
sudo apt-get install libncurses5-dev
在编译时需要加上-lncurses
选项
在运行编译好的二进制文件时也要安装ncurses库
#include
int main()
{
initscr(); // 初始化,进入ncurses模式,创建虚拟屏幕
printw("hello world"); // 在虚拟屏幕上光标位置打印 hello world
refresh(); // 将虚拟屏幕上的内容写到显示器上,并刷新
getchar(); // libc
endwin(); // 推出ncurses模式
}
将终端屏幕初始化为curses模式,该函数初始化了curses系统并且为当前屏幕(“stdscr”)和相关的数据结构分配内存。
printw函数用于向stdscr虚拟屏幕缓冲区写入数据,refresh函数负责将stdscr缓冲区中的数据显示在屏幕上。refresh只核查窗口和数据中变动的部分。
释放了curses子系统和相关数据结构占用的内存,使得能够正常返回控制台模式,否则程序推出后终端显示会变得异常。
初始化后curses session的模式及功能包括:terminal mode, color mode, mouse mode 等
一般而言,终端驱动程序会缓冲用户输入的字符,直到遇到换行符或者回车符后,这些字符才可以被使用。raw和cbreak可以禁止行缓冲(line buffering):row可以处理ctrl+z, ctrl+c等控制字符,将其传送至程序而不产生终端信号;cbreak则不会这样处理.
noecho() 禁止输入的字符出现在屏幕上
为stdscr激活功能键 keypad(stdscr, true)
以 0.1 s 为单位等待用户输入,若在规定的时间内没有输入则返回#define ERR -1
#include
#include
#include
int main()
{
initscr(); // 开始curses模式
int ch;
curs_set(false); // 关闭光标显示
raw(); // 禁用输入缓冲
keypad(stdscr, TRUE); // 没有它当按下Fn时程序似乎不正常
noecho(); // 当执行getch函数时关闭键盘回显
// 向缓冲区stdscr中写数据
printw("Type any character to seee it in bold\n");
// 用法同getchar,但又有区别,可尝试换成getchar会怎样
// curses库中getch与getchar用法相似,但如果用getchar函数会出现的显示上的问题
// 这个问题有待进一步探究
ch = getch(); // 如果没有raw()函数必须按下enter时才将字符传给程序
for (int i = 1; i<=12; ++i) {
// 如果没有keypad将不会执行这条语句
if (ch == KEY_F(i)) {
printw("F%d Key pressed", i);
// 如果没有noecho一些控制字符将被打印到屏幕上
goto conti_exe;
}
}
printw("The pressed key is ");
attron(A_BOLD); // 看名知意
printw("%c", ch);
attroff(A_BOLD);
conti_exe:
refresh(); // 将stdscr的内容显示到屏幕
getch(); // 等待用户输入
endwin(); // 结束curses模式
}
printw(string); // 在窗口stdscr的当前坐标输出string
refresh();
// w+ 指定窗口显示
wprintw(win, string); // 在win上写string
wrefresh(win); // 刷新窗口win
// mv+ 在指定位置打印
mvprintw(y, x, string); 在stdscr的(y, x)处写string
mvwprintw(win, y, x, string); // 在win的(y, x)处写string
addch()系列:将单一的字符打印到屏幕上,可以附加字符修饰参数的一类函数
printw()系列:类似printf格式化输出
addstr()系列:打印字符串
addch( ch | A_BOLD | A_UNDERLINE);
attrset(), 不可叠加文本属性
attron(), attroff() 可叠加文本属性
以 ACS_ 开头的宏可用于绘制一些简单的表格、线条等
vwprintw()和vprintf()相似,用于打印变量表中所对应的变量(没用过)
指定窗口 | 指定位置 | 指定窗口+位置 | |
---|---|---|---|
addch | waddch | mvaddch | mvwaddch |
addstr | waddstr | mvaddstr | mvwaddstr |
printw | wprintw | mvprintw | mvwprintw |
getmaxyx
initscr();
curs_set(false);
raw();
keypad(stdscr, TRUE);
noecho();
char mesg[] = "Just a string";
int row, col;
getmaxyx(stdscr, row, col);
mvprintw(row/2, (col-strlen(mesg))/2, "%s", mesg);
mvprintw(row-2, 0, "This screen has %d rows and %d columns\n", row, col);
printw("Try resizing your window(if possible and then run this prog)");
refresh();
getch();
endwin();
getch() 系列:读取一个字符
scanw()系列:按照格式化读取输入
getstr() 系列:读取字符串
scanw | wscanw | mvscanw | mvwscanw |
getch | wgetch | mvgetch | mvwgetch |
char mesg[] = "Just a string";
char str[80];
int row, col;
getmaxyx(stdscr, row, col);
mvprintw(LINES/2, (COLS-strlen(mesg))/2, "%s", mesg);
getstr(str);
mvprintw(LINES-2, 0, "You ENtered:%s\n", str);
printw("row:%d, col:%d, LINES:%d", row, col, LINES);
#include
#include
#include
#include
#include
int main(int argc, char* argv[])
{
//
int ch, prev;
FILE *fp;
int goto_prev = false, y, x; /* sdfg*/
if (argc != 2)
{
printf("error");
exit(1);
}
fp = fopen(argv[1], "r");
if (fp == NULL)
{
perror("Connot open inputfile");
exit(1);
}
initscr();
curs_set(false);
raw();
keypad(stdscr, TRUE);
noecho();
prev = EOF;
while ((ch = fgetc(fp)) != EOF)
{
if (prev == '/' && ch == '*')
{
attron(A_BOLD);
goto_prev = true;
}
if (goto_prev == true)
{
getyx(stdscr, y, x);
move(y, x -1);
printw("%c%c", '/', ch);
ch = 'a';
goto_prev = false;
}
else
{
printw("%c", ch);
}
refresh();
if (prev == '*' && ch == '/')
{
attroff(A_BOLD);
}
prev = ch;
}
///
refresh();
getch();
endwin();
}
宏 | 说明 |
---|---|
A_NORMAL | 普通字符 |
… | … |
名 | 说明 |
---|---|
attrset | 会覆盖之前的设置 |
attron | 会追加 |
attroff | 只会关闭特定修饰 |
standend() | 等价于attrset(A_NORMAL) |
attr_get() | 获得当前窗口修饰属性设置及背景、文字颜色 需要在设置的修饰之后才能使用 |
attr_类函数 | |
wattr_类函数 | |
chgat() | |
wchgat() | |
mvchgat() | |
mvwchgat() |
start_color();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
printw("A Big string which i didn't care to type fully");
mvchgat(0, 10, 4, A_BLINK, 1, NULL);
// 第三个参数表示从光标开始的向后几个字符,-1代表整行,
声明 | 说明 |
---|---|
WINDOW * newwin (h, w, y, x); | 创建窗口结构体 |
int delwin(WINDOW*); | 释放窗口资源 |
int wborder(win, L, R, U, D, 左上, 右上,左下,右下) | 绘制边框 |
int mvhline(y, x, char, num) | draw h line |
int mvvline(y, x, char, num) | draw v line |
假象stdscr有个二维数组存储窗口中的内容,newwin是在这个二维数组中划分
在原有的stdscr窗口中创建新的窗口,
#include
#include
#include
#include
#include
WINDOW* create_nwin(int h, int w, int y, int x)
{
WINDOW* local_win;
local_win = newwin(h, w, y, x);
// box(local_win, 0, 0);
wborder(local_win,'*','*','*','*','#','#','#','#');
wrefresh(local_win);
return local_win;
}
void del_win(WINDOW* local)
{
wborder(local,' ',' ',' ',' ',' ',' ',' ',' ');
wrefresh(local);
delwin(local);
}
int main(int argc, char* argv[])
{
initscr();
curs_set(false);
raw();
keypad(stdscr, TRUE);
noecho();
//
WINDOW* myw;
int w = 10, h = 7, x = (COLS-w)/2, y = (LINES-h)/2;
int ch;
printw("Press F1 to exit");
refresh();
myw = create_nwin(h, w, y, x);
while ((ch = getch()) != KEY_F(1))
{
switch (ch)
{
case KEY_LEFT:
del_win(myw);
myw = create_nwin(h, w, y, --x);
break;
case KEY_RIGHT:
del_win(myw);
myw = create_nwin(h, w, y, ++x);
break;
case KEY_UP:
del_win(myw);
myw = create_nwin(h, w, --y, x);
break;
case KEY_DOWN:
del_win(myw);
myw = create_nwin(h, w, ++y, x);
break;
default:
break;
}
}
///
// getch();
endwin();
}
声明 | 说明 | ||
---|---|---|---|
bool has_colors(void) | 检测当前终端是否支持颜色显示 | ||
int start_color() | 启动颜色机制,初始化相关内容 | ||
init_pair(颜色号,前景色,背景色) | 定义颜色对,定义好颜色对后就可以将号传给COLOR_PAIR(n)宏, attron(COLOR_PAIR(n)) | ||
init_color(COLOR_RED颜色名,R, G, B); | 改变某个颜色的RGB值, rgb的值从0到1000 | ||
color_content() pair_content() |
查看当前颜色设置 |
宏 | 值 | 颜色 |
---|---|---|
COLOR_BLACK | 0 | 黑 |
COLOR_MAGENTA | 5 | 洋红色 |
COLOR_CYAN | 6 | 蓝绿,青色 |
COLOR_ |
easy menu
#include
#include
#define WIDTH 30
#define HEIGHT 10
int startx = 0;
int starty = 0;
char* choices[] = {
"File",
"Edit",
"Selection",
"View"
};
int n_choices = sizeof(choices) / sizeof(char*);
void print_menu(WINDOW* menu_win, int highlight)
{
int x = 2, y = 2;
box(menu_win, 0, 0);
for (int i = 0; i < n_choices; ++i)
{
if (highlight == i + 1)
{
wattron(menu_win, A_REVERSE);
mvwprintw(menu_win, y, x, "%s", choices[i]);
wattroff(menu_win, A_REVERSE);
}
else
{
mvwprintw(menu_win, y, x, "%s", choices[i]);
}
++y;
}
wrefresh(menu_win);
}
void main()
{
WINDOW* menu_win;
int highlight = 1;
int choice = 0;
int c;
initscr();
curs_set(false);
clear();
noecho();
raw();
startx = (80 - WIDTH) / 2;
starty = (24 - HEIGHT) / 2;
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
keypad(menu_win, TRUE);
mvprintw(0, 0, "Use");
refresh();
print_menu(menu_win, highlight);
while (1)
{
c = wgetch(menu_win);
switch (c)
{
case KEY_UP:
if (highlight == 1)
{
highlight = n_choices;
}
else
{
--highlight;
}
break;
case KEY_DOWN:
if (highlight == n_choices)
{
highlight = 1;
}
else
{
++highlight;
}
break;
case 10:
choice = highlight;
break;
default:
mvprintw(24, 0, "press is %3d hopelly can be printed as %c", c, c);
refresh();
break;
}
print_menu(menu_win, highlight);
if (choice != 0) break;
}
mvprintw(23, 0, "You cho %d with choice string %s\n", choice, choices[choice-1]);
clrtoeol();
refresh();
endwin();
}