linux下的图形库
在屏幕左上角打印Hello, World
#include
int main()
{
initscr(); // 初始化屏幕,默认stdscr
printw("Hello World");// 与printf相似但是打印到虚拟窗口stdscr
refresh();// 需要刷新才能显示到屏幕上
getch(); // 等待用户输入
endwin(); // 关闭窗口
return 0;
}
都是关闭行缓冲,两者的区别是raw
不会产生信号(CTRL+C CTRL +Z)。
输入的内容是否回显
开启功能按键,F1、F2、方向键等。
用法:
keypad(stdscr, TRUE)
延迟等待多少秒,若没反应则返回一个ERR。
#include
int main()
{
int ch;
initscr();
raw();
keypad(stdscr, TRUE); /* 获取功能按钮 */
noecho(); /* 不回显 */
printw("Type any character to see it in bold\n");
ch = getch();
if(ch == KEY_F(1)) /* 按下F1键 */
printw("F1 Key pressed");
else
{ printw("The pressed key is ");
attron(A_BOLD); // 加粗
printw("%c", ch);
attroff(A_BOLD);
}
refresh(); /*虚拟屏幕打印到实际屏幕 */
getch();
endwin();
return 0;
}
ncurse
中w
前缀的都是指定窗口,带mv
的都是移动到(x,y)
进行操作。
比如
printw(string);// 在stdscr当前位置打印字符串
mvprintw(y, x, string);/* 到(y,x)处打印字符串*/
wprintw(win, string); /* 在窗口win上打印字符串*/
mvwprintw(win, y, x, string); /* 移动到win窗口的(y,x)位置打印字符串*/
输出单个字符,移动游标。
还有
mvaddch(row, col, c)
waddch(win, c)
mvwaddch(win, row, col, c)
字符有颜色、加粗等属性。可以通过两种方式添加
addch(ch | A_BOLD | A_UNDERLINE)
attron() attroff() attrset()
后面介绍输出字符串,与printf
类似。
printw(str)
wprintw(win, str);
mvwprintw(y,x,win,str)
vwprintw() => vprintf()
给指定窗口输出字符串
addstr()
mvaddstr()
....
这些函数都是(y,x)
, 首先传入纵轴,再是横轴。
getmaxyx()
是获取窗口大小的函数。
#include
#include
int main()
{
char mesg[]="Just a string";
int row,col;
initscr();
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 program again");
refresh();
getch();
endwin();
return 0;
}
输入单个函数。cbreak()
关闭行缓冲,noecho()
关闭回显。
与sscanf
类似,通过wgetstr
获取的行来进行扫描。
scanw()
wscanw()
mvwscanw()
vwscanw() => vscanf()
获取一个字符串
#include /* ncurses.h includes stdio.h */
#include
int main()
{
char mesg[]="Enter a string: ";
char str[80];
int row,col;
initscr();
getmaxyx(stdscr,row,col);
mvprintw(row/2,(col−strlen(mesg))/2,"%s",mesg);
getstr(str);// 获取字符串
mvprintw(LINES − 2, 0, "You Entered: %s", str);
getch();
endwin();
return 0;
}
getyx()
获取游标当前位置
move
移动游标
读取.c
文件,加粗注释。
#include
#include
int main(int argc, char *argv[])
{
int ch, prev, row, col;
prev = EOF;
FILE *fp;
int y, x;
if(argc != 2)
{
printf("Usage: %s \n", argv[0]);
exit(1);
}
fp = fopen(argv[1], "r");
if(fp == NULL)
{
perror("Cannot open input file");
exit(1);
}
initscr();
getmaxyx(stdscr, row, col);
while((ch = fgetc(fp)) != EOF)
{
getyx(stdscr, y, x);
if(y == (row − 1))
{
printw("<−Press Any Key−>");
getch();
clear(); /*清屏*/
move(0, 0); /*回到开头*/
}
if(prev == '/' && ch == '*') /*确定注释开始*/
{
attron(A_BOLD); /* 加粗 */
getyx(stdscr, y, x); /* 获取当前位置 */
move(y, x − 1); /* 回退*/
printw("%c%c", '/', ch); /* 输出 */
}
else
printw("%c", ch);
refresh();
if(prev == '*' && ch == '/')
attroff(A_BOLD); /* 关闭加粗选项*/
prev = ch;
}
endwin();
fclose(fp);
return 0;
}
在头文件里面, 使用
attron(A_REVERSE | A_BOLD)
#define WA_ATTRIBUTES A_ATTRIBUTES
#define WA_NORMAL A_NORMAL
#define WA_STANDOUT A_STANDOUT
#define WA_UNDERLINE A_UNDERLINE
#define WA_REVERSE A_REVERSE
#define WA_BLINK A_BLINK
#define WA_DIM A_DIM
#define WA_BOLD A_BOLD
#define WA_ALTCHARSET A_ALTCHARSET
#define WA_INVIS A_INVIS
#define WA_PROTECT A_PROTECT
#define WA_HORIZONTAL A_HORIZONTAL
#define WA_LEFT A_LEFT
#define WA_LOW A_LOW
#define WA_RIGHT A_RIGHT
#define WA_TOP A_TOP
#define WA_VERTICAL A_VERTICAL
attrset()
删了重来
attron()
只影响它自己指定的。
获取属性
与前面函数一样,只是需要传入attr_t
类型参数。还有扩展的wattr
系函数。
在不移动游标的情况下,设置一组字符的属性值。
chgat(−1, A_REVERSE, 0, NULL);
// 第一个参数,几个字符
// 第二个参数,属性值
// 第三个参数,颜色值
// 第四个参数,一直为NULL
使用样例
#include
int main(int argc, char *argv[])
{ initscr();
start_color();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
printw("A Big string which i didn't care to type fully ");
mvchgat(0, 0, −1, A_BLINK, 1, NULL);
refresh();
getch();
endwin(); /* End curses mode */
return 0;
}
ncurse中的一个重要概念,之前的大多数操作大多是在stdscr
上进行的。
newwin()
delwin()
box(win, ch1, ch2)
// ch1 ch2 分别是边界上水平和垂直的字符
border(ls, rs, ts, bs, tl, tr, bl, br)
mvvline(y,x,ch1, num)
// 生成竖线
mvhline(y,x,ch2, num)
// 生成横线
// l: left s: side
#include
WINDOW *create_newwin(int height, int width, int starty, int startx);
void destroy_win(WINDOW *local_win);
int main(int argc, char *argv[])
{ WINDOW *my_win;
int startx, starty, width, height;
int ch;
initscr();
cbreak();
keypad(stdscr, TRUE); // 按F1需要
height = 3;
width = 10;
starty = (LINES − height) / 2;
startx = (COLS − width) / 2;
printw("Press F1 to exit");
refresh();
my_win = create_newwin(height, width, starty, startx);
while((ch = getch()) != KEY_F(1))
{ switch(ch)
{ case KEY_LEFT:
destroy_win(my_win);
my_win = create_newwin(height, width, starty,−−startx);
break;
case KEY_RIGHT:
destroy_win(my_win);
my_win = create_newwin(height, width, starty,++startx);
break;
case KEY_UP:
destroy_win(my_win);
my_win = create_newwin(height, width, −−starty,startx);
break;
case KEY_DOWN:
destroy_win(my_win);
my_win = create_newwin(height, width, ++starty,startx);
break;
}
}
endwin(); /* End curses mode */
return 0;
}
WINDOW *create_newwin(int height, int width, int starty, int startx)
{ WINDOW *local_win;
local_win = newwin(height, width, starty, startx);
box(local_win, 0 , 0);
wrefresh(local_win);
return local_win;
}
void destroy_win(WINDOW *local_win)
{
wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
wrefresh(local_win);
delwin(local_win);
}
#include
typedef struct _win_border_struct {
chtype ls, rs, ts, bs,
tl, tr, bl, br;
}WIN_BORDER;
typedef struct _WIN_struct {
int startx, starty;
int height, width;
WIN_BORDER border;
}WIN;
void init_win_params(WIN *p_win);
void print_win_params(WIN *p_win);
void create_box(WIN *win, bool flag);
int main(int argc, char *argv[])
{ WIN win;
int ch;
initscr(); /* Start curses mode */
start_color(); /* Start the color functionality */
cbreak(); /* Line buffering disabled, Pass on
* everty thing to me */
keypad(stdscr, TRUE); /* I need that nifty F1 */
noecho();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
init_win_params(&win);
print_win_params(&win);
attron(COLOR_PAIR(1));
printw("Press F1 to exit");
refresh();
attroff(COLOR_PAIR(1));
create_box(&win, TRUE);
while((ch = getch()) != KEY_F(1))
{ switch(ch)
{ case KEY_LEFT:
create_box(&win, FALSE);
−−win.startx;
create_box(&win, TRUE);
break;
case KEY_RIGHT:
create_box(&win, FALSE);
++win.startx;
create_box(&win, TRUE);
break;
case KEY_UP:
create_box(&win, FALSE);
−−win.starty;
create_box(&win, TRUE);
break;
case KEY_DOWN:
create_box(&win, FALSE);
++win.starty;
create_box(&win, TRUE);
break;
}
}
endwin();
return 0;
}
void init_win_params(WIN *p_win)
{
p_win−>height = 3;
p_win−>width = 10;
p_win−>starty = (LINES − p_win−>height)/2;
p_win−>startx = (COLS − p_win−>width)/2;
p_win−>border.ls = '|';
p_win−>border.rs = '|';
p_win−>border.ts = '−';
p_win−>border.bs = '−';
p_win−>border.tl = '+';
p_win−>border.tr = '+';
p_win−>border.bl = '+';
p_win−>border.br = '+';
}
void print_win_params(WIN *p_win)
{
#ifdef _DEBUG
mvprintw(25, 0, "%d %d %d %d", p_win−>startx, p_win−>starty,
p_win−>width, p_win−>height);
refresh();
#endif
}
void create_box(WIN *p_win, bool flag)
{ int i, j;
int x, y, w, h;
x = p_win−>startx;
y = p_win−>starty;
w = p_win−>width;
h = p_win−>height;
if(flag == TRUE)
{ mvaddch(y, x, p_win−>border.tl);
mvaddch(y, x + w, p_win−>border.tr);
mvaddch(y + h, x, p_win−>border.bl);
mvaddch(y + h, x + w, p_win−>border.br);
mvhline(y, x + 1, p_win−>border.ts, w − 1);
mvhline(y + h, x + 1, p_win−>border.bs, w − 1);
mvvline(y + 1, x, p_win−>border.ls, h − 1);
mvvline(y + 1, x + w, p_win−>border.rs, h − 1);
}
else
for(j = y; j <= y + h; ++j)
for(i = x; i <= x + w; ++i)
mvaddch(j, i, ' ');
refresh();
}
has_colors()
来测试是否有颜色,start_color()
在使用颜色之前需要进行调用。
init_color()
初始化颜色。
#include
void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
int main(int argc, char *argv[])
{
initscr();
if(has_colors() == FALSE)
{
endwin();
printf("Your terminal does not support color\n");
exit(1);
}
start_color();
init_pair(1, COLOR_RED, COLOR_BLACK);
attron(COLOR_PAIR(1));
print_in_middle(stdscr, LINES / 2, 0, 0, "Viola !!! In color ...");
attroff(COLOR_PAIR(1));
getch();
endwin();
}
void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string)
{ int length, x, y;
float temp;
if(win == NULL)
win = stdscr;
getyx(win, y, x);
if(startx != 0)
x = startx;
if(starty != 0)
y = starty;
if(width == 0)
width = 80;
length = strlen(string);
temp = (width − length)/ 2;
x = startx + (int)temp;
mvwprintw(win, y, x, "%s", string);
refresh();
}
#define COLOR_BLACK 0
#define COLOR_RED 1
#define COLOR_GREEN 2
#define COLOR_YELLOW 3
#define COLOR_BLUE 4
#define COLOR_MAGENTA 5
#define COLOR_CYAN 6
#define COLOR_WHITE 7
用init_color(COLOR_RED, 0, 0, 400)
后面跟的是颜色的rgb的值。
color_content()
和pair_content()
可以获取颜色内容,前景、背景对。
不移动游标的情况下,改变一组字符的颜色。
chgat(−1, A_REVERSE, 0, NULL)
使用例子
#include
int main(int argc, char *argv[])
{
initscr();
start_color();
init_pair(1, COLOR_CYAN, COLOR_BLACK);
printw("A Big string which i didn't care to type fully ");
mvchgat(0, 0, −1, A_BLINK, 1, NULL);
refresh();
getch();
endwin(); /* End curses mode */
return 0;
}
接受键盘的信号还是通过输入字符的判断来实现的。
int ch;
ch = getch();
if (ch == KEY_F1)
...// 应用逻辑
#include
#include
#define WIDTH 30
#define HEIGHT 10
int startx = 0;
int starty = 0;
char *choices[] = {
"Choice 1",
"Choice 2",
"Choice 3",
"Choice 4",
"Exit",
};
int n_choices = sizeof(choices) / sizeof(char *);
void print_menu(WINDOW *menu_win, int highlight);
int main()
{ WINDOW *menu_win;
int highlight = 1;
int choice = 0;
int c;
initscr();
clear();
noecho();
cbreak(); /* Line buffering disabled. pass on everything */
startx = (80 - WIDTH) / 2;
starty = (24 - HEIGHT) / 2;
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
keypad(menu_win, TRUE);
mvprintw(0, 0, "Use arrow keys to go up and down, Press enter to select a choice");
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, "Charcter pressed is = %3d Hopefully it can be printed as '%c'", c, c);
refresh();
break;
}
print_menu(menu_win, highlight);
if(choice != 0) /* User did a choice come out of the infinite loop */
break;
}
mvprintw(23, 0, "You chose choice %d with choice string %s\n", choice, choices[choice - 1]);
clrtoeol();
refresh();
endwin();
return 0;
}
void print_menu(WINDOW *menu_win, int highlight)
{
int x, y, i;
x = 2;
y = 2;
box(menu_win, 0, 0);
for(i = 0; i < n_choices; ++i)
{ if(highlight == i + 1) /* High light the present choice */
{ 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);
}
需要用函数mousemask( mmask_t newmask, mmask_t *oldmask)
来开启监听鼠标的事件。
鼠标事件
BUTTON1_PRESSED mouse button 1 down
BUTTON1_RELEASED mouse button 1 up
BUTTON1_CLICKED mouse button 1 clicked
BUTTON1_DOUBLE_CLICKED mouse button 1 double clicked
BUTTON1_TRIPLE_CLICKED mouse button 1 triple clicked
BUTTON2_PRESSED mouse button 2 down
BUTTON2_RELEASED mouse button 2 up
BUTTON2_CLICKED mouse button 2 clicked
BUTTON2_DOUBLE_CLICKED mouse button 2 double clicked
BUTTON2_TRIPLE_CLICKED mouse button 2 triple clicked
BUTTON3_PRESSED mouse button 3 down
BUTTON3_RELEASED mouse button 3 up
BUTTON3_CLICKED mouse button 3 clicked
BUTTON3_DOUBLE_CLICKED mouse button 3 double clicked
BUTTON3_TRIPLE_CLICKED mouse button 3 triple clicked
BUTTON4_PRESSED mouse button 4 down
BUTTON4_RELEASED mouse button 4 up
BUTTON4_CLICKED mouse button 4 clicked
BUTTON4_DOUBLE_CLICKED mouse button 4 double clicked
BUTTON4_TRIPLE_CLICKED mouse button 4 triple clicked
BUTTON_SHIFT shift was down during button state change
BUTTON_CTRL control was down during button state change
BUTTON_ALT alt was down during button state change
ALL_MOUSE_EVENTS report all button state changes
REPORT_MOUSE_POSITION report mouse movement
通过getMouse(MEVENT *)
来获取鼠标事件的状态。
事件的结构体
typedef struct
{
short id; /* ID to distinguish multiple devices */
int x, y, z; /* event coordinates */
mmask_t bstate; /* button state bits */
}
判断事件发生
MEVENT event;
ch = getch();
if(ch == KEY_MOUSE)
if(getmouse(&event) == OK)
. /* Do some thing with the event */
.
.
if(event.bstate & BUTTON1_PRESSED)
printw("Left Button Pressed");
#include
#define WIDTH 30
#define HEIGHT 10
int startx = 0;
int starty = 0;
char *choices[] = { "Choice 1",
"Choice 2",
"Choice 3",
"Choice 4",
"Exit",
};
int n_choices = sizeof(choices) / sizeof(char *);
void print_menu(WINDOW *menu_win, int highlight);
void report_choice(int mouse_x, int mouse_y, int *p_choice);
int main()
{ int c, choice = 0;
WINDOW *menu_win;
MEVENT event;
/* Initialize curses */
initscr();
clear();
noecho();
cbreak(); //Line buffering disabled. pass on everything
/* Try to put the window in the middle of screen */
startx = (80 - WIDTH) / 2;
starty = (24 - HEIGHT) / 2;
attron(A_REVERSE);
mvprintw(23, 1, "Click on Exit to quit (Works best in a virtual console)");
refresh();
attroff(A_REVERSE);
/* Print the menu for the first time */
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
print_menu(menu_win, 1);
/* Get all the mouse events */
mousemask(ALL_MOUSE_EVENTS, NULL);
while(1)
{ c = wgetch(menu_win);
switch(c)
{ case KEY_MOUSE:
if(getmouse(&event) == OK)
{ /* When the user clicks left mouse button */
if(event.bstate & BUTTON1_PRESSED)
{ report_choice(event.x + 1, event.y + 1, &choice);
if(choice == -1) //Exit chosen
goto end;
mvprintw(22, 1, "Choice made is : %d String Chosen is \"%10s\"", choice, choices[choice - 1]);
refresh();
}
}
print_menu(menu_win, choice);
break;
}
}
end:
endwin();
return 0;
}
void print_menu(WINDOW *menu_win, int highlight)
{
int x, y, i;
x = 2;
y = 2;
box(menu_win, 0, 0);
for(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);
}
/* Report the choice according to mouse position */
void report_choice(int mouse_x, int mouse_y, int *p_choice)
{ int i,j, choice;
i = startx + 2;
j = starty + 3;
for(choice = 0; choice < n_choices; ++choice)
if(mouse_y == j + choice && mouse_x >= i && mouse_x <= i + strlen(choices[choice]))
{ if(choice == n_choices - 1)
*p_choice = -1;
else
*p_choice = choice + 1;
break;
}
}
取得游标此时的坐标
保存屏幕信息
putwin()
保存窗口信息到文件
getwin()
copywin()
游标可见性设置
0 : invisible or
1 : normal or
2 : very visible.
#include
int main()
{
initscr(); /* Start curses mode */
printw("Hello World !!!\n"); /* Print Hello World */
refresh(); /* Print it on to the real screen */
def_prog_mode(); /* Save the tty modes */
endwin(); /* End curses mode temporarily */
system("/bin/sh"); /* Do whatever you like in cooked mode */
reset_prog_mode(); /* Return to the previous tty mode*/
/* stored by def_prog_mode() */
refresh(); /* Do refresh() to restore the */
/* Screen contents */
printw("Another String\n"); /* Back to curses use the full */
refresh(); /* capabilities of curses */
endwin(); /* End curses mode */
return 0;
}
#include
int main()
{
initscr();
printw("Upper left corner "); addch(ACS_ULCORNER); printw("\n");
printw("Lower left corner "); addch(ACS_LLCORNER); printw("\n");
printw("Lower right corner "); addch(ACS_LRCORNER); printw("\n");
printw("Tee pointing right "); addch(ACS_LTEE); printw("\n");
printw("Tee pointing left "); addch(ACS_RTEE); printw("\n");
printw("Tee pointing up "); addch(ACS_BTEE); printw("\n");
printw("Tee pointing down "); addch(ACS_TTEE); printw("\n");
printw("Horizontal line "); addch(ACS_HLINE); printw("\n");
printw("Vertical line "); addch(ACS_VLINE); printw("\n");
printw("Large Plus or cross over "); addch(ACS_PLUS); printw("\n");
printw("Scan Line 1 "); addch(ACS_S1); printw("\n");
printw("Scan Line 3 "); addch(ACS_S3); printw("\n");
printw("Scan Line 7 "); addch(ACS_S7); printw("\n");
printw("Scan Line 9 "); addch(ACS_S9); printw("\n");
printw("Diamond "); addch(ACS_DIAMOND); printw("\n");
printw("Checker board (stipple) "); addch(ACS_CKBOARD); printw("\n");
printw("Degree Symbol "); addch(ACS_DEGREE); printw("\n");
printw("Plus/Minus Symbol "); addch(ACS_PLMINUS); printw("\n");
printw("Bullet "); addch(ACS_BULLET); printw("\n");
printw("Arrow Pointing Left "); addch(ACS_LARROW); printw("\n");
printw("Arrow Pointing Right "); addch(ACS_RARROW); printw("\n");
printw("Arrow Pointing Down "); addch(ACS_DARROW); printw("\n");
printw("Arrow Pointing Up "); addch(ACS_UARROW); printw("\n");
printw("Board of squares "); addch(ACS_BOARD); printw("\n");
printw("Lantern Symbol "); addch(ACS_LANTERN); printw("\n");
printw("Solid Square Block "); addch(ACS_BLOCK); printw("\n");
printw("Less/Equal sign "); addch(ACS_LEQUAL); printw("\n");
printw("Greater/Equal sign "); addch(ACS_GEQUAL); printw("\n");
printw("Pi "); addch(ACS_PI); printw("\n");
printw("Not equal "); addch(ACS_NEQUAL); printw("\n");
printw("UK pound sign "); addch(ACS_STERLING); printw("\n");
refresh();
getch();
endwin();
return 0;
}
linux-ho-to