UNIX 螢幕導向程式的發展利器 - curses (之二)(轉)
UNIX 螢幕導向程式的發展利器 - curses (之二)(轉)[@more@]UNIX 螢幕導向程式的發展利器 - curses (之二)
作者:林建宏
在上期為您介紹完了 curses.h 函式庫的一些基本函式呼叫後在, 在本期裡
, 我們將繼續為您介紹 curses 有關多視窗處理的函式. 有了這些函式, 我們
可以在程式裡同時處理多個不同的視窗. 如 joe 編輯器內我們可將螢幕切割
成好幾個小螢幕, 並且可以在這些不同的螢幕間做切換並編輯不同的檔案, 這
就是多視處理的應用. 另外, 有關 POP-UP 視窗的製作, 以及視窗的捲動, 在
本文裡, 我們將以簡單的例子, 告訴您這些功能是如何做到的. 關於一些較基
本函式的用法, 我們將不再特別介紹. 如果您尚未熟悉 curses 基本函式使用
方法, 請參閱上一期 (80 期 ) 通訊.
■ 視窗的建立
視窗的建立, 以 newwin() 這個函式來完成. 同時, 需宣告此視窗為 WINDOW
結構變數.
WINDOW *newwin(lines,colums,start_y,start_x);
WINDOW *win;
win=newwin(10,20,0,0);
如此, 將以 (0,0) 為原點, 取一個 10 列 20 行的矩形為一新的視窗. 今後
我們只要呼叫 win 這個變數, 就可以對這新視窗做處理.
如: wmove(win,3,2);
■ 多視窗處理函式的格式
這一類函式和一般的基本函式極為類似, 幾乎每一個基本函式都有一個對應的
視窗處理函式. 一般將 'w' 加在函式的裡頭作為區別, 'w' 乃 'window' 之
意. 另外, 因為可同時處理多個視窗, 在呼叫使用時, 需特別指定欲處理的視
窗. 當然, 如果您指定對 stdscr 做處理, 由於是對標準輸出入螢幕處理, 其
作用將相當於一般基本的函式.
如:
wmove(win,y,x) 即對 win 這個視窗做 move() 動作.
wmove(stdscr,y,x) 相當於 move(y,x)
介紹一些較重要的函式
wmove(win,y,x)
touchwin(win)
wrefresh(win)
mvwaddstr(win,y,x,str)
wattron(attr)
delwin(win)
subwin(win,ny,nx,y,x)
其他函式多和基本函式互為對應, 故不全部列出, 詳細名稱可參考 curses
的 online manual.
■ 視窗內的座標系
視窗內的座標系, 將以此視窗的起始點為新原點, 並以其相對位置作為新的
座標. 舉例來說
win=newwin(10,20,5,5);
wmove(win,2,3);
將以 (5,5) 為新原點, y 方向移動 2 單位, x 方向移動 3 單位. 因此實際
上, 遊標將移動至 y=7 x=8 的位置上.
■ POP-UP 視窗的建立
利用 curses 所提供的視窗處理函式, 我們可以做出像 ONLINE HELP 的 POP
-UP 畫面. 當按下某鍵後, 一個新的視窗將像 " 跳 " 出來一般覆蓋原來的畫
面. 當關掉此視窗後, 又不會影響到原來被覆蓋的畫面.
下面的例子, 我們及模擬 ONLINE HELP 的形式, 當按下 'h' 鍵時, 視窗即出現
#include
main()
{
int ch,x,y;
WINDOW *win;
initscr(); ←┐
cbreak; │ 啟動 curses 模式
noecho(); │
nonl(); ←┘
win=newwin(4,30,LINES/2-3, COLS/2-15);/* 建立一個新視窗, 其中LINES,COLS
*/
box(win,'|','-'); /* 為 curses 內定值,
即螢幕行/列數*/
mvwaddstr(win,1,4,"This is another screen");
mvwaddstr(win,2,2,"Press anykey to continue..");
for (y=0;y for (x=0;x mvprintw(y,x,"@");
for(;;) {
refresh();
ch=getch();
switch(ch) {
case 'q': /* 按 'q' 鍵離開 */
endwin();
exit(0);
case ' ': /* 按 [TAB] 鍵 呼叫另一視窗 */
touchwin(win); /* wrefresh() 前需 touchwin() */
wrefresh(win);
getch(); /* 按任意鍵關閉視窗 */
touchwin(stdscr);
break;
default:break;
}
}
}
執行結果:
┌————————————————————————————┐
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
└————————————————————————————┘
↑ 原來畫面被 '@' 填滿, 按下[TAB]鍵後
↓ 出現 POP-UP 畫面.
┌————————————————————————————┐
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │
│ @@@@@@@@@@@@@| This is another screen |@@@@@@@@@@@ │
│ @@@@@@@@@@@@@| Press anykey to continue.. |@@@@@@@@@@@ │
│ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
└————————————————————————————┘
■ 視窗的捲動
視窗的捲動, 掖Q用來配合視窗的處理, 當我們持續對視窗輸出直到視窗的遊
標移動至最後一列時, 如果我們再輸出一列或是輸出一個換行字元時, 視窗可
整個往上捲動一行. 這對我們撰寫一個編輯程式時, 是尤其重要的, 一個畫面
無法捲動的編輯器, 勢必無法處理超過一個螢幕大小的檔案.
視窗的捲動是預設為關閉的, 並以 scrollok() 來控制開閉.
scrollok(win,TRUE); 開啟
scrollok(win,FALSE); 關閉
下面的例子因為不斷地輸出 0,1,2.. 故將以一個 40 * 10 的視窗不停的捲動
#include
main()
{
int i;
WINDOW *scrwin,*boxwin;
initscr(); ←┐
cbreak; │ 啟動 curses 模式
noecho(); │
nonl(); ←┘
scrwin=newwin(10,40,LINES/2-6,COLS/2-25); /* 設定另一視窗大小 */
boxwin=newwin(12,42,LINES/2-7,COLS/2-26); /* 設定外框視窗大小 */
scrollok(scrwin,TRUE); /* 開啟視窗捲動功能 */
box(boxwin,'|','-');
refresh();
wrefresh(boxwin);
for (i=0;;++i) /* 不斷地在視窗內輸出 0-8 的數字,使視窗捲動
*/
{
wprintw(scrwin,"%d",i%9);
wrefresh(scrwin);
}
}
執行結果:
┌——————————————————————┐
│ □---------------------□ │
│ |3456780123456780123412| ↑ 視 │
│ |3456780123456780123456| │ 窗 │
│ |7801234567801234567801| │ 不 │
│ |2345678012345678012345| │ 停 │
│ |6780123456780123456780| │ 往 │
│ |1234567801234567801234| │ 上 │
│ |5678012345678012345678| │ 卷 │
│ |0123456780123456780123| │ 動 │
│ □---------------------□ │
│ │
└——————————————————————┘
■ □例 - 模擬 joe 分割畫面同時編輯兩個檔案
在下面的例子裡, 我們應用了多視窗處理的函式, 改良上回介紹的編輯器,
在這個程式裡, 我們可以同時編輯兩個畫面, 並以 [ESC] 做不同視窗間的
切換. 同時, 按下 [TAB] 鍵, 會出現 POP-UP 的 ONLINE HELP.
#include
void initial();
main()
{
WINDOW *win[2],*curwin,*helpwin;
int nowwin;
int x,y;
int i;
int ch;
initial();
win[0]=newwin(LINES/2-1,COLS-1,0,0); /* 設定兩個視窗的大小*/
win[1]=newwin(LINES/2-1,COLS-1,LINES/2,0);
helpwin=newwin(3,30,2,COLS/2-15 ); /* ONLINE HELP 的大小 */
box(helpwin,'|','-');
mvwaddstr(helpwin,0,10,"ONLINE HELP"); /* ONLINE HELP 的內容 */
mvwaddstr(helpwin,1,4,"Hit any key to continue..");
for (i=0;i mvaddch(LINES/2-1,i,'-');
nowwin=0; /* 先指定遊標在第一視窗 */
curwin=win[nowwin];
getyx(curwin,y,x);
move(0,0);
refresh();
refresh();
do {
ch=getch();
switch(ch) {
case KEY_UP: --y; /* 判斷是否"↑"鍵被按下 */
break;
case KEY_DOWN: ++y; /* 判斷是否"↓"鍵被按下 */
break;
case KEY_RIGHT: ++x; /* 判斷是否"→"鍵被按下 */
break;
case KEY_LEFT: --x; /* 判斷是否"←"鍵被按下 */
break;
case ' ': /* 判斷是否 ENTER 鍵被按下 */
++y;
x=0;
break;
case ' ': /* 判斷是否 TAB 鍵被按下 */
touchwin(helpwin);
wrefresh(helpwin); /* 呼叫 ONLINE HELP */
getch();
touchwin(win[1-nowwin]); /* 重畫第一,二視窗 */
wrefresh(win[1-nowwin]);
touchwin(curwin);
wrefresh(curwin);
break;
case 127: /* 判斷是否 BACKSPACE 鍵被按下 */
wmove(curwin,y,--x);/* delete 一個字元 */
waddch(curwin,' ');
break;
case 27 : nowwin=1-nowwin; /* [ESC] 鍵切換視窗 */
curwin=win[nowwin];
getyx(curwin,y,x);
break;
default:
waddch(curwin,ch);
x++;
break;
}
wmove(curwin,y,x);
wrefresh(curwin);
} while(1);
}
void initial()
{
initscr(); ←┐
cbreak(); │ 啟動 curses 模式
nonl(); │
noecho(); ←┘
intrflush(stdscr,FALSE);
keypad(stdscr,TRUE);
refresh();
}
執行結果:
┌—————————————————————————————┐
│ screen1 │
┌→ │ this is screen 1, you can press [ESC] to │
以 │ │ switch between screen 1 and screen 2. │
[ESC]│ │ │
切 │ │ │
換 │ │----------------------------------------------------------│
遊 │ │ screen 2 │
標 │ │ │
位 └→ │ _ (遊標) │
置 │ │
└—————————————————————————————┘
↑ 按下[TAB] 鍵,出現 ONLINE HELP
↓
┌—————————————————————————————┐
│ screen1 │
│ this is screen 1, you can press [ESC] to │
│ switch□--------ONLINE HELP--------□ │
│ | Hit any key to continue..| │
│ □---------------------------□ │
│----------------------------------------------------------│
│ screen 2 │
│ │
│ │
│ │
└—————————————————————————————┘
↑ 按任意鍵, ONLINE HELP 關閉
↓
┌—————————————————————————————┐
│ screen1 │
│ this is screen 1, you can press [ESC] to │
│ switch between screen 1 and screen 2. │
│ │
│ │
│----------------------------------------------------------│
│ screen 2 │
│ │
│ _ (遊標) │
│ │
└—————————————————————————————┘
■ 結語
我們以連續兩期來介紹 curses.h 函式庫的使用方法, 相信同學對撰寫這類的
程式應該不再陌生. 所謂『戲法人人會變, 巧妙各有不同』. 知道了基本函式
的呼叫方法, 能不能寫出實用的程式, 就靠各位的巧思和創造力了.
有任何問題建議, 歡迎 E-mail 至 ljh@CCCA.NCTU.edu.tw , 謝謝 !
發信人: Cardinal.bbs@mic.ee.ntu.edu.tw (Cardinal), 信區: unix
標 題: Re: 請問誰會用 curses 顯示 ANSI color 字
發信站: 臺大電機 Maxwell 站
首先宣告,這一封的內容應該屬於 programming board,但是現在有不止一個
人問我這個問題,所以在這個版再把詳細的方法說明一遍。如果有人看不懂而
仍然有興趣的,請 mail 給我 (Cardinal.bbs@mic.ee.ntu.edu.tw) ,不要在
這邊 reply,我會考慮在私下或在 programming board解決你的問題。
==> 在 Cardinal@Maxwell (Cardinal) 的文章中提到:
: 1.開一個 new window (newwin)
: 2.設定 window 的彩色屬性 (wattrset)
==> 在設定彩色屬性之前應該先設定顏色的 "pair" ,所謂的 "pair" 是指
foreground及background的顏色。curses的顏色有下面幾種 (type為
short) :
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
用init_pair(short pair, short f_color, short b_color)來設定 pair,
for example:
init_pair(100, COLOR_RED, COLOR_BLUE)
就設定了編號為 100, 藍底紅字的 color pair 了.
另外你要是嫌這幾種顏色太單調了, 可以用 init_color 來設定色彩, 細節
這邊就不談了.
然後就用 wattrset(WINDOW* pwindow, short color_pair)設定你window的
顏色, for example:
wattrset(pwindow, 100) 就設定了一個藍底紅字的 window (不要忘記
這兒的 100 是剛剛用 init_pair設定的值)
: 3.印在 window 的字就自動變成那個顏色了 (mvwprintw, mvwaddstr, ...)
==> 這句... 該不會有問題吧.
: 4.想要印不同顏色的字,只要把那個字 "OR" (|) 不同的顏色即可 (記住,
: 這種有屬性的字要用 int,不能用 char)
==> 其實型別不是用 int, 而是用 chtype (不過沒有差別, 去查查 curses.h就
知道) , 譬如說, 你想要在剛剛設定為藍底紅字的 window印一個別的顏色的
'A' 字, 可以這麼做 :
init_pair(another_color_pair, COLOR_隨便, COLOR_隨便) -->先設定另一
個 color pair
char cascii = 'A';
chtype cascii_color = cascii | another_color_pair;
再把 cascii_color 印出來就是一個你想要顏色的 A 了.
--
~ Cardinal ~
From: Cardinal (Cardinal)
Title: 關於精華區...
Date: Fri Mar 10 20:36:27 1995
您好:
在 programming 版精華區 unix - curses libraries 中有一篇文章是我寫的,
剛剛來這邊找資料時翻到的, 真是受寵若驚. 不過原來的文章 (如何用 curses
顯示彩色) 有一點忘了提到, 希望您能把下面的說明加進去:
1. init_color及init_pair 是 SystemVR3以後的標準, 不適用於 BSD 或
SunOS.
2. 在 SunOS 上要達成這樣的目的, 我知道的有兩種解法
a.有一款大同的中文工作站有支援 init_color & init_pair 的 library
這一型的 library 與 SunOS 為 object-code compatible.
b.ncurses 支援 init_pair & init_color
作者:林建宏
在上期為您介紹完了 curses.h 函式庫的一些基本函式呼叫後在, 在本期裡
, 我們將繼續為您介紹 curses 有關多視窗處理的函式. 有了這些函式, 我們
可以在程式裡同時處理多個不同的視窗. 如 joe 編輯器內我們可將螢幕切割
成好幾個小螢幕, 並且可以在這些不同的螢幕間做切換並編輯不同的檔案, 這
就是多視處理的應用. 另外, 有關 POP-UP 視窗的製作, 以及視窗的捲動, 在
本文裡, 我們將以簡單的例子, 告訴您這些功能是如何做到的. 關於一些較基
本函式的用法, 我們將不再特別介紹. 如果您尚未熟悉 curses 基本函式使用
方法, 請參閱上一期 (80 期 ) 通訊.
■ 視窗的建立
視窗的建立, 以 newwin() 這個函式來完成. 同時, 需宣告此視窗為 WINDOW
結構變數.
WINDOW *newwin(lines,colums,start_y,start_x);
WINDOW *win;
win=newwin(10,20,0,0);
如此, 將以 (0,0) 為原點, 取一個 10 列 20 行的矩形為一新的視窗. 今後
我們只要呼叫 win 這個變數, 就可以對這新視窗做處理.
如: wmove(win,3,2);
■ 多視窗處理函式的格式
這一類函式和一般的基本函式極為類似, 幾乎每一個基本函式都有一個對應的
視窗處理函式. 一般將 'w' 加在函式的裡頭作為區別, 'w' 乃 'window' 之
意. 另外, 因為可同時處理多個視窗, 在呼叫使用時, 需特別指定欲處理的視
窗. 當然, 如果您指定對 stdscr 做處理, 由於是對標準輸出入螢幕處理, 其
作用將相當於一般基本的函式.
如:
wmove(win,y,x) 即對 win 這個視窗做 move() 動作.
wmove(stdscr,y,x) 相當於 move(y,x)
介紹一些較重要的函式
wmove(win,y,x)
touchwin(win)
wrefresh(win)
mvwaddstr(win,y,x,str)
wattron(attr)
delwin(win)
subwin(win,ny,nx,y,x)
其他函式多和基本函式互為對應, 故不全部列出, 詳細名稱可參考 curses
的 online manual.
■ 視窗內的座標系
視窗內的座標系, 將以此視窗的起始點為新原點, 並以其相對位置作為新的
座標. 舉例來說
win=newwin(10,20,5,5);
wmove(win,2,3);
將以 (5,5) 為新原點, y 方向移動 2 單位, x 方向移動 3 單位. 因此實際
上, 遊標將移動至 y=7 x=8 的位置上.
■ POP-UP 視窗的建立
利用 curses 所提供的視窗處理函式, 我們可以做出像 ONLINE HELP 的 POP
-UP 畫面. 當按下某鍵後, 一個新的視窗將像 " 跳 " 出來一般覆蓋原來的畫
面. 當關掉此視窗後, 又不會影響到原來被覆蓋的畫面.
下面的例子, 我們及模擬 ONLINE HELP 的形式, 當按下 'h' 鍵時, 視窗即出現
#include
main()
{
int ch,x,y;
WINDOW *win;
initscr(); ←┐
cbreak; │ 啟動 curses 模式
noecho(); │
nonl(); ←┘
win=newwin(4,30,LINES/2-3, COLS/2-15);/* 建立一個新視窗, 其中LINES,COLS
*/
box(win,'|','-'); /* 為 curses 內定值,
即螢幕行/列數*/
mvwaddstr(win,1,4,"This is another screen");
mvwaddstr(win,2,2,"Press anykey to continue..");
for (y=0;y
for(;;) {
refresh();
ch=getch();
switch(ch) {
case 'q': /* 按 'q' 鍵離開 */
endwin();
exit(0);
case ' ': /* 按 [TAB] 鍵 呼叫另一視窗 */
touchwin(win); /* wrefresh() 前需 touchwin() */
wrefresh(win);
getch(); /* 按任意鍵關閉視窗 */
touchwin(stdscr);
break;
default:break;
}
}
}
執行結果:
┌————————————————————————————┐
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
└————————————————————————————┘
↑ 原來畫面被 '@' 填滿, 按下[TAB]鍵後
↓ 出現 POP-UP 畫面.
┌————————————————————————————┐
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │
│ @@@@@@@@@@@@@| This is another screen |@@@@@@@@@@@ │
│ @@@@@@@@@@@@@| Press anykey to continue.. |@@@@@@@@@@@ │
│ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
│ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
└————————————————————————————┘
■ 視窗的捲動
視窗的捲動, 掖Q用來配合視窗的處理, 當我們持續對視窗輸出直到視窗的遊
標移動至最後一列時, 如果我們再輸出一列或是輸出一個換行字元時, 視窗可
整個往上捲動一行. 這對我們撰寫一個編輯程式時, 是尤其重要的, 一個畫面
無法捲動的編輯器, 勢必無法處理超過一個螢幕大小的檔案.
視窗的捲動是預設為關閉的, 並以 scrollok() 來控制開閉.
scrollok(win,TRUE); 開啟
scrollok(win,FALSE); 關閉
下面的例子因為不斷地輸出 0,1,2.. 故將以一個 40 * 10 的視窗不停的捲動
#include
main()
{
int i;
WINDOW *scrwin,*boxwin;
initscr(); ←┐
cbreak; │ 啟動 curses 模式
noecho(); │
nonl(); ←┘
scrwin=newwin(10,40,LINES/2-6,COLS/2-25); /* 設定另一視窗大小 */
boxwin=newwin(12,42,LINES/2-7,COLS/2-26); /* 設定外框視窗大小 */
scrollok(scrwin,TRUE); /* 開啟視窗捲動功能 */
box(boxwin,'|','-');
refresh();
wrefresh(boxwin);
for (i=0;;++i) /* 不斷地在視窗內輸出 0-8 的數字,使視窗捲動
*/
{
wprintw(scrwin,"%d",i%9);
wrefresh(scrwin);
}
}
執行結果:
┌——————————————————————┐
│ □---------------------□ │
│ |3456780123456780123412| ↑ 視 │
│ |3456780123456780123456| │ 窗 │
│ |7801234567801234567801| │ 不 │
│ |2345678012345678012345| │ 停 │
│ |6780123456780123456780| │ 往 │
│ |1234567801234567801234| │ 上 │
│ |5678012345678012345678| │ 卷 │
│ |0123456780123456780123| │ 動 │
│ □---------------------□ │
│ │
└——————————————————————┘
■ □例 - 模擬 joe 分割畫面同時編輯兩個檔案
在下面的例子裡, 我們應用了多視窗處理的函式, 改良上回介紹的編輯器,
在這個程式裡, 我們可以同時編輯兩個畫面, 並以 [ESC] 做不同視窗間的
切換. 同時, 按下 [TAB] 鍵, 會出現 POP-UP 的 ONLINE HELP.
#include
void initial();
main()
{
WINDOW *win[2],*curwin,*helpwin;
int nowwin;
int x,y;
int i;
int ch;
initial();
win[0]=newwin(LINES/2-1,COLS-1,0,0); /* 設定兩個視窗的大小*/
win[1]=newwin(LINES/2-1,COLS-1,LINES/2,0);
helpwin=newwin(3,30,2,COLS/2-15 ); /* ONLINE HELP 的大小 */
box(helpwin,'|','-');
mvwaddstr(helpwin,0,10,"ONLINE HELP"); /* ONLINE HELP 的內容 */
mvwaddstr(helpwin,1,4,"Hit any key to continue..");
for (i=0;i
nowwin=0; /* 先指定遊標在第一視窗 */
curwin=win[nowwin];
getyx(curwin,y,x);
move(0,0);
refresh();
refresh();
do {
ch=getch();
switch(ch) {
case KEY_UP: --y; /* 判斷是否"↑"鍵被按下 */
break;
case KEY_DOWN: ++y; /* 判斷是否"↓"鍵被按下 */
break;
case KEY_RIGHT: ++x; /* 判斷是否"→"鍵被按下 */
break;
case KEY_LEFT: --x; /* 判斷是否"←"鍵被按下 */
break;
case ' ': /* 判斷是否 ENTER 鍵被按下 */
++y;
x=0;
break;
case ' ': /* 判斷是否 TAB 鍵被按下 */
touchwin(helpwin);
wrefresh(helpwin); /* 呼叫 ONLINE HELP */
getch();
touchwin(win[1-nowwin]); /* 重畫第一,二視窗 */
wrefresh(win[1-nowwin]);
touchwin(curwin);
wrefresh(curwin);
break;
case 127: /* 判斷是否 BACKSPACE 鍵被按下 */
wmove(curwin,y,--x);/* delete 一個字元 */
waddch(curwin,' ');
break;
case 27 : nowwin=1-nowwin; /* [ESC] 鍵切換視窗 */
curwin=win[nowwin];
getyx(curwin,y,x);
break;
default:
waddch(curwin,ch);
x++;
break;
}
wmove(curwin,y,x);
wrefresh(curwin);
} while(1);
}
void initial()
{
initscr(); ←┐
cbreak(); │ 啟動 curses 模式
nonl(); │
noecho(); ←┘
intrflush(stdscr,FALSE);
keypad(stdscr,TRUE);
refresh();
}
執行結果:
┌—————————————————————————————┐
│ screen1 │
┌→ │ this is screen 1, you can press [ESC] to │
以 │ │ switch between screen 1 and screen 2. │
[ESC]│ │ │
切 │ │ │
換 │ │----------------------------------------------------------│
遊 │ │ screen 2 │
標 │ │ │
位 └→ │ _ (遊標) │
置 │ │
└—————————————————————————————┘
↑ 按下[TAB] 鍵,出現 ONLINE HELP
↓
┌—————————————————————————————┐
│ screen1 │
│ this is screen 1, you can press [ESC] to │
│ switch□--------ONLINE HELP--------□ │
│ | Hit any key to continue..| │
│ □---------------------------□ │
│----------------------------------------------------------│
│ screen 2 │
│ │
│ │
│ │
└—————————————————————————————┘
↑ 按任意鍵, ONLINE HELP 關閉
↓
┌—————————————————————————————┐
│ screen1 │
│ this is screen 1, you can press [ESC] to │
│ switch between screen 1 and screen 2. │
│ │
│ │
│----------------------------------------------------------│
│ screen 2 │
│ │
│ _ (遊標) │
│ │
└—————————————————————————————┘
■ 結語
我們以連續兩期來介紹 curses.h 函式庫的使用方法, 相信同學對撰寫這類的
程式應該不再陌生. 所謂『戲法人人會變, 巧妙各有不同』. 知道了基本函式
的呼叫方法, 能不能寫出實用的程式, 就靠各位的巧思和創造力了.
有任何問題建議, 歡迎 E-mail 至 ljh@CCCA.NCTU.edu.tw , 謝謝 !
發信人: Cardinal.bbs@mic.ee.ntu.edu.tw (Cardinal), 信區: unix
標 題: Re: 請問誰會用 curses 顯示 ANSI color 字
發信站: 臺大電機 Maxwell 站
首先宣告,這一封的內容應該屬於 programming board,但是現在有不止一個
人問我這個問題,所以在這個版再把詳細的方法說明一遍。如果有人看不懂而
仍然有興趣的,請 mail 給我 (Cardinal.bbs@mic.ee.ntu.edu.tw) ,不要在
這邊 reply,我會考慮在私下或在 programming board解決你的問題。
==> 在 Cardinal@Maxwell (Cardinal) 的文章中提到:
: 1.開一個 new window (newwin)
: 2.設定 window 的彩色屬性 (wattrset)
==> 在設定彩色屬性之前應該先設定顏色的 "pair" ,所謂的 "pair" 是指
foreground及background的顏色。curses的顏色有下面幾種 (type為
short) :
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
用init_pair(short pair, short f_color, short b_color)來設定 pair,
for example:
init_pair(100, COLOR_RED, COLOR_BLUE)
就設定了編號為 100, 藍底紅字的 color pair 了.
另外你要是嫌這幾種顏色太單調了, 可以用 init_color 來設定色彩, 細節
這邊就不談了.
然後就用 wattrset(WINDOW* pwindow, short color_pair)設定你window的
顏色, for example:
wattrset(pwindow, 100) 就設定了一個藍底紅字的 window (不要忘記
這兒的 100 是剛剛用 init_pair設定的值)
: 3.印在 window 的字就自動變成那個顏色了 (mvwprintw, mvwaddstr, ...)
==> 這句... 該不會有問題吧.
: 4.想要印不同顏色的字,只要把那個字 "OR" (|) 不同的顏色即可 (記住,
: 這種有屬性的字要用 int,不能用 char)
==> 其實型別不是用 int, 而是用 chtype (不過沒有差別, 去查查 curses.h就
知道) , 譬如說, 你想要在剛剛設定為藍底紅字的 window印一個別的顏色的
'A' 字, 可以這麼做 :
init_pair(another_color_pair, COLOR_隨便, COLOR_隨便) -->先設定另一
個 color pair
char cascii = 'A';
chtype cascii_color = cascii | another_color_pair;
再把 cascii_color 印出來就是一個你想要顏色的 A 了.
--
~ Cardinal ~
From: Cardinal (Cardinal)
Title: 關於精華區...
Date: Fri Mar 10 20:36:27 1995
您好:
在 programming 版精華區 unix - curses libraries 中有一篇文章是我寫的,
剛剛來這邊找資料時翻到的, 真是受寵若驚. 不過原來的文章 (如何用 curses
顯示彩色) 有一點忘了提到, 希望您能把下面的說明加進去:
1. init_color及init_pair 是 SystemVR3以後的標準, 不適用於 BSD 或
SunOS.
2. 在 SunOS 上要達成這樣的目的, 我知道的有兩種解法
a.有一款大同的中文工作站有支援 init_color & init_pair 的 library
這一型的 library 與 SunOS 為 object-code compatible.
b.ncurses 支援 init_pair & init_color
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10796304/viewspace-962556/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在Unix下用C編寫curses程式的一些常用模組(轉)
- iOS中的螢幕導航iOS
- UNIX系統都會提供的螢幕編輯器-vi的使用(轉)
- 關於螢幕程式設計(轉)程式設計
- 判斷螢幕旋轉的事件程式碼事件
- ubuntu螢幕旋轉Ubuntu
- 程式導向和麵向物件的對比(轉)物件
- 螢幕取詞核心內幕 (轉)
- 用VB製作螢幕保護程式 (轉)
- 利用VB編寫螢幕保護程式 (轉)
- 物件導向的軟體開發 (轉)物件
- 研發活動的專案導向(轉)
- 物件導向的JavaScript程式設計 (轉)物件JavaScript程式設計
- orientationchange 螢幕旋轉事件事件
- 2014年螢幕將會向什麼方向發展?採用量子點最新技術
- 《JavaScript物件導向精要》之二:函式JavaScript物件函式
- iOS開發 詳解強制螢幕旋轉的方法iOS
- 最簡單的螢幕複製程式(象素複製) (轉)
- ios一句程式碼搞定螢幕旋轉iOS
- 讓應用程式禁止Windows螢幕保護 (轉)Windows
- 程式設計師的“橫向發展”程式設計師
- Unix檔案安全檢查利器- Tripwire(轉)
- IHS Markit:AMOLED 螢幕驅動晶片發展趨勢淺析晶片
- 程式導向與物件導向物件
- 物件導向與程式導向物件
- 螢幕控制示例程式
- php中的程式導向與物件導向PHP物件
- Java的秘密:使用全螢幕模式 (轉)Java模式
- java物件導向程式設計(轉)Java物件程式設計
- Android 禁止螢幕旋轉Android
- mui 控制旋轉螢幕方向UI
- 滑鼠螢幕取詞 原理 (轉)
- js判斷螢幕是否旋轉程式碼例項JS
- 用C#Builder編寫螢幕保護程式 (轉)UI
- 從程式導向到物件導向物件
- 向React Native應用新增螢幕捕捉功能React Native
- WebRTC本地分享螢幕,錄製螢幕Web
- iOS螢幕旋轉解決方案iOS