簡介
Linux/Unix編程給人的感覺就比較"cool"一點,好像Linux編程都是在黑黑的終端下進行的。確實是這樣,許多Linux高手都喜歡在終端方式下工作,熟悉了一些命令以後,這樣的工作方式效率還是很高的。但是長久地看著黑黑的螢幕難免讓人感到厭倦,有沒有一種工具能讓我們在Linux下編出好看的圖形呢?答案是肯定的,它就是curses!
curses的名字起源於"cursor optimization",即游標最佳化。它最早由有美國伯克利大學的Bill Joy和Ken Arnold編寫的,用來處理一個遊戲rogue的螢幕顯示。後來貝爾實驗室的Mark Horton在System III Unix中重新編寫了curses。現在幾乎所有的Unix/Linux作業系統都帶了curses函式館,curses也加入了對滑鼠的支持,一些選單和面板的處理。可以說,curses是Linux終端圖形編程的不二選擇(比如著名的文字編輯器 vi 就是基於curses編的)。
安裝
Ubuntu下安裝方法:
sudo apt-get install libncurses5-dev
(如果發現找不到這個包,使用命令 sudo apt-get update 更新下包源)
用法
1. 包含頭檔案:curses.h
2. 編譯時應加上連結語句-lcurses,如:gcc temp.c -o temp -lcurses
3. 重要的函式:
函式 | 功能 |
initscr() | 初始化curses庫和ttty (在開始curses編程之前,必須使用initscr()這個函式來開啟curses模式) |
endwin() | 關閉curses並重置tty (結束curses編程時,最後調用的一個函式) |
move(y,x) | 將游標移動至 x,y 的位置 |
getyx(win,y,x) | 得到目前游標的位置(請注意!是 y,x 而不是&y,&x) |
clear() and erase() | 將整個螢幕清除(請注意配合refresh() 使用) |
echochar(ch) | 顯示某個字元 |
addch(ch) | 在當前位置畫字元ch |
mvaddch(y,x,ch) | 在(x,y) 上顯示某個字元。相當於呼叫move(y,x);addch(ch); |
addstr(str) | 在當前位置畫字元串str |
mvaddstr(y,x,str) | 在(x,y) 上顯示一串字串。相當於呼叫move(y,x);addstr(str); |
printw(format,str) | 類似 printf() ,以一定的格式輸出至螢幕 |
mvprintw(y,x,format,str) | 在(x,y) 位置上做 printw 的工作。相當於呼叫move(y,x);printw(format,str); |
getch() | 從鍵盤讀取一個字元。(注意!傳回的是整數值) |
getstr() | 從鍵盤讀取一串字元。 |
scanw(format,&arg1,&arg2...) | 如同 scanf,從鍵盤讀取一串字元。 |
beep() | 發出一聲嗶聲 |
box(win,ch1,ch2) | 自動畫方框 |
refresh() | 使螢幕按照你的意圖顯示。比較工作螢幕和真實螢幕的差異,然後refresh通過終端驅動送出那些能使真實螢幕於工作螢幕一致的字元和控制碼。(工作螢幕就像磁碟快取,curses中的大部分的函式都只對它進行修改) |
standout() | 啟動standout模式(一般使螢幕發色) |
standend() | 關閉standout模式 |
常用的初始化函式集合:
例子
首先我們應該了解,在終端使用的螢幕模式是基於文本的。所以在開始使用curses前,需要用initscr()函式初始化螢幕。對應的,程式結束需要調用endwin();函式來關閉curses狀態。
有了這個概念, 我們就可以來寫著名的"Hello, world!"之curses版了:
呵呵, 剛才忘了說了. 我們調用curses庫一般是用C語言的(沒什麼奇怪, C可以說是Linux的官方語言, 不過你也可以用C++或Python等語言調用curses的, 這無關緊要). 假設我們把這個程式保存為 hello.c
不過不要急著用gcc -o hello hello.c去編譯運行(我知道你會用gcc:) 那樣是不能通過編譯的. 因為curses庫不在標準路徑上, 所以我們要加上 -lcurses連線選項, 像這樣:
gcc -o hello hello.c -lcurses
現在你用 ./hello 運行一下程式看看,是不是出現了你所期望的視窗.
現在我們來一行行分析一下代碼.
#include <curses.h> /*這是每個 curses 程式都必須包含的頭檔案,表明使用了curses庫*/
然後主函式中第一句initscr();初始化了螢幕, 使之開始進入curses圖形化工作方式.
其實我們現在沒有自己建立視窗, 用的是標準螢幕 stdscr(就象C裡面標準輸入stdin, 標準輸出stdout一個概念), 它就是我們面前的電腦螢幕(不過現在還是黑黑的:)
下面一句: box(stdscr, ACS_VLINE, ACS_HLINE); 畫了一個框. 有了這個框我們才有"窗體"的感覺. stdscr就是標準螢幕, ACS_VLINE和ACS_HLINE代表構成方框兩邊的基本元素, 你也可以用 '|'和'-'代替, 不過可能沒有ACS_VLINE, ACS_HLINE好看了.
move(LINES/2, COLS/2);
waddstr(stdscr, "Hello, world!");
這兩句是把游標移到螢幕中間, 然後輸出我們的"Hello, world!"
LINES 和 COLS是curses定義的宏, 代表當前螢幕的最大行數和列數. waddstr()函式的作用是在stdscr上列印字元串"hello, world!"
螢幕分物理螢幕(我們所看到的)和邏輯螢幕(在記憶體中的), 我們調用函式時修改的是邏輯螢幕,它不會在當前物理螢幕上顯示出來.所以現在螢幕上還是什麼也沒有, 需要調用refresh()把我們對邏輯螢幕的改動在物理螢幕(顯示器)上顯示出來. 然後用getch()讓螢幕暫停一下.
最後調用endwin()結束curses, 恢復原來的螢幕.
好了, 我們完成了第一個例子的分析. 是不是挺簡單的?
不過不盡如人意的是螢幕還是那個樣子, 沒有什麼色彩. 要加色彩? 那也是挺容易的: 首先用start_color()函式開啟顏色模式, 然後設定我們要的顏色就行了.
curses里的顏色是配對的, 要一個背景色對一個前景色. 使用之前用init_pair()初始化.
比如init_pair(1, COLOR_BLUE, COLOR_GREEN);就定義了一組顏色, COLOR_BLUE為前景色, COLOR_GREEN為背景色. 1是它們的標記號碼(供其他函式調用時使用) 我們來看一個簡單的例子:
這個程式假如保存為color.c
那么你可以這樣編譯了: gcc -o color color.c -lcurses
用./color一運行, 是不是有幾個彩色的字? 呵呵, 雖然不好看, 但是說不定你自己以後可以用curses寫出精美的程式.
ubuntu 用戶 如果 沒有 curses.h庫,可以用一下命令下載: apt-get install libncurses5-dev
如果想做更多了解,可以去下邊網址看看:
http://www.ibm.com/developerworks/cn/aix/library/au-shellcurses/index.html