CUI 字元介面
GUI:圖形介面
使用一套封裝庫 libcruses.so
老版本 libcurses.so
新版本 libncruses.so
編譯時間需要-lcurses 或者-lncurses
如果標頭檔curses.h不存在 則嘗試使用ncurses.h
printf /scanf標準IO
大部分標準IO重新導向到 /dev/tty /det/pts/1
curses就是終端輸出
為了防止printf重新導向到終端破壞UI,禁止用printf輸出
1 編程模型
初始化終端 WINDOW* initscr();
返回一個被初始化的表單
操作終端(輸入/輸出/定位/重新整理)
釋放終端 int endwin()
2 顯示
2.1 圖形輸出
border 列印一個邊框
int border(chtype ls, chtype rs, chtype ts, chtype bs,
chtype tl, chtype tr, chtype bl, chtype br);
8個參數分別為 左 右 上 下 左上 右上 左下 右下 的字元
可以採用8個0來採用預設邊框
border('a','b','c','e','f','g','h','g');
border(0,0,0,0,0,0,0,0);
wborder 在指定表單畫一個邊框
box 列印一個邊框
int box(WINDOW *win, chtype verch, chtype horch);
box需要表單,只能設定水平和垂直的邊框字元
標準螢幕除了在init_scr()的返回外 還可以使用全域變數stdscr
box(stdscr,0,0); 效果和border(0,0,0,0,0,0,0,0);是一樣的
hline 畫水平線
hline 在 標準表單 游標位置 畫水平線
whline 在 指定表單 游標位置 畫水平線
mvhline 在 標準表單 指定位置 畫水平線
mvwhline 在 指定表單 指標位置 畫水平線
vline 畫垂直線(同hline)
屬性字元:位元組=屬性位元組+字元位元組
注意:
box需要表單
initscr返回被初始化的表單:標準螢幕
curses定義了一個全域變數stdscr表示標準表單
命名規則:
*** 某函數
w*** 在某表單運行某函數
mv*** 在指定位置運行某函數
mvw***
在指定表單指定位置運行某函數
2.2刷屏
void refresh(); //將輸出立刻顯示出來 一般習慣來說是輸出之後立刻refresh
void wrefresh(WINDOW*);
從裡到外刷屏
3 字元輸出
int addch(const chtype ch);
int waddch(WINDOW *win, const chtype ch);
int mvaddch(int y, int x, const chtype ch);
int mvwaddch(WINDOW *win, int y, int x, const chtype ch);
屬性字元: ' '|屬性
(字元 位預算符 屬性)
屬性(man attron中的)
A_NORMAL Normal display (no highlight)
A_STANDOUT Best highlighting mode of the terminal.
A_UNDERLINE Underlining
A_REVERSE Reverse video
A_BLINK Blinking
A_DIM Half bright
A_BOLD Extra bright or bold
A_PROTECT Protected mode
A_INVIS Invisible or blank mode
A_ALTCHARSET Alternate character set
A_CHARTEXT Bit-mask to extract a character
COLOR_PAIR(n) Color-pair number n
特殊字元
man addch中還可以找到不知到如何列印的字元 譬如PI
ACS_PI * greek pi
ACS_PLMINUS # plus/minus
ACS_PLUS + plus
ACS_RARROW > arrow pointing right
ACS_RTEE + right tee
ACS_S1 - scan line 1
等等
3 字元屬性與顏色
顏色屬性
3.1 判定終端是否支援顏色(現在的終端一般都支援,可以不做判定)
bool has_colors(void);
3.2 初始化顏色
int start_color(void);
3.3 定義顏色對
int init_pair(short pair, short f, short b);
編號 前景色彩背景色
最多支援8對顏色 1-8
顏色可選的有:
COLOR_BLACK
COLOR_RED
COLOR_GREEN
COLOR_YELLOW
COLOR_BLUE
COLOR_MAGENTA 紫色
COLOR_CYAN 青色
COLOR_WHITE
if(has_colors() == TRUE)
{
start_color(); //初始化顏色
init_pair(1,COLOR_RED,COLOR_YELLOW);
init_pair(2,COLOR_BLUE,COLOR_WHITE);
init_pair(3,COLOR_BLACK,COLOR_WHITE);
bkgd(COLOR_PAIR(3));
}
3.4 使用顏色對(宏)
COLOR_PAIR(short pair)
設定字元顏色 在字元的屬性中設定
mvaddch(2,10,'A'|A_UNDERLINE|COLOR_PAIR(1));
設定背景顏色 bkgd 函數
init_pair(3,COLOR_BLACK,COLOR_WHITE);
bkgd(COLOR_PAIR(3)); //設定背景色
這組函數一定要在init_scr之後使用
#include <curses.h>
int main()
{
initscr();//初始化表單
if(has_colors() == TRUE)
{
start_color(); //初始化顏色
init_pair(1,COLOR_RED,COLOR_YELLOW); //定義顏色對
init_pair(2,COLOR_BLUE,COLOR_CYAN);
init_pair(3,COLOR_BLACK,COLOR_WHITE);
bkgd(COLOR_PAIR(3)); //設定背景色
}
box(stdscr,0,0);//輸出邊框
mvaddch(2,10,'A'|A_UNDERLINE|COLOR_PAIR(1)); //輸出字元
mvaddch(10,20,'B'|A_BOLD|COLOR_PAIR(1));
mvaddch(10,21,ACS_PI|COLOR_PAIR(2));//輸出特殊字元
getch();
endwin();//釋放表單
}
3.5 輸出字串addstr
int addstr(const char *str);輸出字串
int addnstr(const char *str, int n); 輸出字串的前n個字元
int waddstr(WINDOW *win, const char *str);
int waddnstr(WINDOW *win, const char *str, int n);
int mvaddstr(int y, int x, const char *str);
int mvaddnstr(int y, int x, const char *str, int n);
int mvwaddstr(WINDOW *win, int y, int x, const char *str);
int mvwaddnstr(WINDOW *win, int y, int x, const char *str, int n);
mvaddstr(1,10,"hello world");//輸出字串
3.6格式字串輸出printw
int printw(const char *fmt, ...);
int wprintw(WINDOW *win, const char *fmt, ...);
int mvprintw(int y, int x, const char *fmt, ...);
int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...);
3.7 設定屬性
attron() 開啟屬性
attroff() 關閉屬性
attron(COLOR_PAIR(1)); //開啟屬性
mvaddstr(1,10,"hello world");//輸出字串
attroff(COLOR_PAIR(1));//關閉屬性
attron(COLOR_PAIR(2)| A_UNDERLINE); //開啟2個屬性
mvaddnstr(3,10,"hahahahaha",3); //控制輸出字串的前幾個字元 此處前3
attroff(COLOR_PAIR(2)| A_UNDERLINE);//關閉2個屬性
案例1:
/*寫一個時間顯示螢幕初始化迴圈顯示時間 並重新整理釋放資源*/#include <curses.h>#include <time.h> //localtime#include <unistd.h> //sleepvoid init();void drawui();void bussiness();void destory();int main(){init();drawui();bussiness();destory();}void init(){initscr();}void destory(){endwin();}void drawui(){box(stdscr,0,0);}void bussiness(){time_t tt;struct tm* t;while(1){tt = time(0);t = localtime(&tt);mvprintw(LINES/2,(COLS-8)/2,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);refresh(); //一定要記得重新整理 不然不顯示sleep(1);}}
案例2:
/*
登入介面
1初始化
2繪製介面
頭
繪製使用者名稱輸入區
繪製密碼輸入區
3等待輸入
4結束
*/
#include <unistd.h>#include <curses.h>#include <string.h>//#include <stdlib.h>void init();void drawLogin();void destory();int main(){init();drawLogin();destory();return 0;}void init(){initscr();}void drawLogin(){char *heads = "BSS BUSSINESS SUPPORT SYSTEM";char *user = "USER[ ]";char *pwd = "PWD [ ]";box(stdscr,0,0);attron(A_BOLD);mvaddstr(3,(COLS-strlen(heads))/2,heads);attroff(A_BOLD);mvhline(4,(COLS-strlen(heads))/2,0,strlen(heads));mvaddstr(8,(COLS-strlen(user))/2,user );mvaddstr(10,(COLS-strlen(pwd))/2,pwd);}void destory(){refresh();getch(); //按一個鍵推出 endwin();}
4 輸入
4.1 字元輸入
int getch(void); 返回輸入的字元 ,並在游標處回顯,游標向前移動
int wgetch(WINDOW *win);
int mvgetch(int y, int x); 返回輸入的字元,並在指定的地方顯示
int mvwgetch(WINDOW *win, int y, int x);
#include <unistd.h>#include <curses.h>#include <string.h>//#include <stdlib.h>void init();void draw();void destory();int main(){init();draw();destory();return 0;}void init(){initscr();}void draw(){char ch;while(1){ch=mvgetch(LINES/2,COLS/2);mvprintw(20,10,"your input is %c(%d)",ch,ch);refresh();}}void destory(){ endwin();}
有些按鍵顯示的結果不正確 在man getch中有
KEY_BREAK Break key
KEY_DOWN The four arrow keys ...
KEY_UP
KEY_LEFT
KEY_RIGHT
KEY_HOME Home key (upward+left arrow)
KEY_BACKSPACE Backspace
KEY_F0 Function keys; space for 64 keys
is reserved.
4.2 控制函數
禁止回顯noecho (預設有回顯)
int noecho(void);
使功能鍵有效 (預設禁用功能鍵)
int keypad(WINDOW *win, bool bf);
//輸出一個字元 並使字元隨著方向鍵移動
#include <curses.h>int main(){int ch,x=5,y=5;initscr();noecho();//防止回顯keypad(stdscr,TRUE); //使功能鍵有效 mvaddch(y,x,'S');while(1){ch = getch();mvaddch(y,x,' ');switch(ch){case KEY_UP :y--;break;case KEY_DOWN:y++;break;case KEY_LEFT:x--;break;case KEY_RIGHT:x++;break;}if(x<0 || y < 0){clear();}mvaddch(y,x,'A');refresh();}endwin();return 0;}
4.3 清屏
int erase(void); //刪除整個螢幕
int werase(WINDOW *win);
int clear(void); //刪除整個螢幕
int wclear(WINDOW *win);
int clrtobot(void);//刪除到螢幕結束
int wclrtobot(WINDOW *win);
int clrtoeol(void); //刪到行尾
int wclrtoeol(WINDOW *win)
4.4 游標控制
1得到游標位置 (這是一個宏)
void getsyx(int y, int x);
設定參數位置
void setsyx(int y, int x);
設定游標是否可見
int curs_set(int visibility);0不可見
4.5輸入字串
int getstr(char *str);
int getnstr(char *str, int n);
int wgetstr(WINDOW *win, char *str);
int wgetnstr(WINDOW *win, char *str, int n);
int mvgetstr(int y, int x, char *str);
int mvwgetstr(WINDOW *win, int y, int x, char *str);
int mvgetnstr(int y, int x, char *str, int n);
4.6格式化輸入字串int scanw(char *fmt, ...);
int wscanw(WINDOW *win, char *fmt, ...);
int mvscanw(int y, int x, char *fmt, ...);
int mvwscanw(WINDOW *win, int y, int x, char *fmt, ...);
#include <unistd.h>#include <curses.h>#include <string.h>//#include <stdlib.h>void init();void draw();void dealInput();void destory();int main(){init();draw();dealInput();destory();return 0;}void init(){initscr();}void draw(){mvaddstr(2,2,"[ ]+[ ]=[ ]");}void dealInput(){int a,b,ch;while(1){mvaddstr(2,3," ");mvaddstr(2,11," ");mvaddstr(2,19," ");mvscanw(2,3,"%d",&a);mvscanw(2,11,"%d",&b);mvprintw(2,19,"%d",a+b);refresh();mvaddstr(3,3,"is continue? (y/n)");ch = getch();if(ch == 'n'){break;}}}void destory(){ endwin();}
5 視窗
為了好看
subwin(); //建立子表單(座標採用子表單座標) 不用
derwin(); //建立子表單(座標採用父表單座標)
WINDOW *derwin(WINDOW *orig, int nlines, int ncols,
int begin_y, int begin_x);
#include <curses.h>int main(){initscr();WINDOW *w;box(stdscr,0,0);w=derwin(stdscr,10,20,2,2);box(w,0,0);refresh();getch();endwin();}
1 在vi設定編碼
:set enconding=編碼 gd2312 utf-8 ios-8859-1
2 在編譯器指定源檔案的編碼 -finput-charset=gb2312
3 在終端指定編碼
4 系統預設編碼