Ncurses: Fenster
<<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
< Spezialtasten | Panels > |
Bisher wurde bei den Programmen nur der Standardscreen stdscr
als Fenster verwendet. Mit ncurses können aber auch eigene Fenster erzeugt und manipuliert werden. Die Funktionen für Fenster sind sehr ähnlich wie die bisher verwendeten. Allerdings sind die speziellen Fenster-Befehle durch den zusätzlichen Buchstaben w
markiert, z.B.:
int wrefresh(WINDOW *win); int wscanw(WINDOW *win, char *fmt, ...); int mvwaddstr(WINDOW *win, int y, int x, const char *str);
Tatsächlich ist es sogar so, dass die bisher verwendeten Standardscreen-Funktionen nur als Makros definiert sind, z.B.:
#define addch(ch) waddch(stdscr,ch) #define attron(at) wattron(stdscr,at) #define bkgd(ch) wbkgd(stdscr,ch) #define clear() wclear(stdscr)
Zum Erzeugen von Fenstern gibt es mehrere Möglichkeiten:
- Neue Fenster erzeugen:
newwin
- Abgeleitete Fenster erzeugen:
subwin, derwin
- Fenster duplizieren:
dupwin
Neue Fenster
BearbeitenWINDOW *newwin(int nlines, int ncols, int begin_y, int begin_x);
Beispiel
Bearbeiten#include <curses.h> #include <stdlib.h> WINDOW *win; void quit(void) { delwin(win); endwin(); } int main(void) { initscr(); atexit(quit); clear(); noecho(); curs_set(0); cbreak(); keypad(stdscr, 1); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); init_pair(2, COLOR_BLUE, COLOR_WHITE); win = newwin(5, 20, 10, 10); bkgd(COLOR_PAIR(1)); wbkgd(win, COLOR_PAIR(2)); mvaddstr(5,5, "Hallo stdscr"); mvwaddstr(win, 3, 3, "Hallo win"); mvwaddstr(win, 7, 3, "Diese Zeichenkette wird nicht angezeigt!"); // da ausserhalb des win-Anzeigebereichs refresh(); wrefresh(win); while(getch() != KEY_F(1)) { } return(0); }
Abgeleitete Fenster
BearbeitenEin subwin
(untergeordnetes Fenster) erbt Eigenschaften vom übergeordneten Fenster.
WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x);
Beispiel: Aufzeigen des Unterschieds von newwin und subwin
Bearbeiten#include <curses.h> #include <stdlib.h> WINDOW *win1, *win2; void quit(void) { delwin(win1); delwin(win2); endwin(); } int main(void) { initscr(); atexit(quit); clear(); noecho(); curs_set(0); cbreak(); keypad(stdscr, 1); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); win1 = newwin(5, 20, 10, 10); win2 = subwin(stdscr, 5, 20, 10, 35); bkgd(COLOR_PAIR(1)); mvaddstr(5,5, "Hallo stdscr"); mvwaddstr(win1, 3, 3, "Hallo newwin"); mvwaddstr(win2, 3, 3, "Hallo subwin"); refresh(); wrefresh(win1); wrefresh(win2); while(getch() != KEY_F(1)) { } return(0); }
derwin
ist im Prinzip das selbe wie subwin
. Während die Position (begin_y, begin_x
) des Fensters bei der Funktion subwin
aber relativ zum Screen festgelegt wird, ist die Position bei derwin
relativ zum orig
-Fenster.
Fensterverzierungen
BearbeitenFenster können auch mit Rahmen oder Begrenzungslinien versehen werden. Diese Verzierungen werden mittels Einzelzeichen aufgebaut. Diese Zeichen können gewöhnliche Buchstaben oder Zahlen sein. Schöner wird das Ganze aber wenn spezielle Zeichen verwendet werden. ncurses kennt "form characters" (ACS, Alternative Character Set), die sich für dieses Aufgabengebiet anbieten. Zu beachten ist, dass Rahmen und Linien wie normaler Text geschrieben werden. Aus diesem Grund können diese Rahmen durch unvorsichtig platzierten Text überschrieben werden. Das bringt zwar keine funktionellen Nachteile, sieht aber nicht schön aus. Dies sollte bei der Verwendung von Rahmen und Linien beachtet werden.
Rahmen
Bearbeitenint border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br); int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br); int box(WINDOW *win, chtype verch, chtype horch);
Erklärung der Parameterbezeichnungen:
- ver ... vertikal
- hor ... horizontal
- l ... left
- r ... right
- b ... bottom
- t ... top
- s ... side
Z.B. bedeuten
ls
... left side, Kante linkstr
... top right, Ecke oben-rechts
Wird 0 übergeben, so wird jeweils das in der Bibliothek festgelegte Standardzeichen verwendet.
Linien
Bearbeitenint hline(chtype ch, int n); int vline(chtype ch, int n); int whline(WINDOW *win, chtype ch, int n); int wvline(WINDOW *win, chtype ch, int n); int mvhline(int y, int x, chtype ch, int n); int mvvline(int y, int x, chtype ch, int n); int mvwhline(WINDOW *, int y, int x, chtype ch, int n); int mvwvline(WINDOW *, int y, int x, chtype ch, int n);
Beispiel
Bearbeiten#include <curses.h> #include <stdlib.h> WINDOW *win; void quit(void) { delwin(win); endwin(); } int main(void) { initscr(); atexit(quit); clear(); noecho(); curs_set(0); cbreak(); keypad(stdscr, 1); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); init_pair(2, COLOR_BLUE, COLOR_WHITE); win = newwin(5, 20, 10, 10); bkgd(COLOR_PAIR(1)); wbkgd(win, COLOR_PAIR(2)); mvaddstr(5,5, "Hallo stdscr"); mvwaddstr(win, 3, 3, "Hallo win"); mvwaddstr(win, 7, 3, "Diese Zeichenkette wird nicht angezeigt!"); // da ausserhalb des win-Anzeigebereichs box(win, 0, 0); mvhline(7, 1, ACS_BULLET, 20); refresh(); wrefresh(win); while(getch() != KEY_F(1)) { } return(0); }
ACS (Liniengrafik, form characters)
BearbeitenObige ACS-Bilder wurden als Screenshoots dieses Programmes erstellt (KDE-Konsole, xterm)
#include <curses.h> #include <stdlib.h> void write_pages(void) { chtype acs_symbol[] = { ACS_ULCORNER, ACS_LLCORNER, ACS_URCORNER, ACS_LRCORNER, ACS_LTEE, ACS_RTEE, ACS_BTEE, ACS_TTEE, ACS_HLINE, ACS_VLINE, ACS_PLUS, ACS_S1, ACS_S9, ACS_DIAMOND, ACS_CKBOARD, ACS_DEGREE, ACS_PLMINUS, ACS_BULLET, ACS_LARROW, ACS_RARROW, ACS_DARROW, ACS_UARROW, ACS_BOARD, ACS_LANTERN, ACS_BLOCK, ACS_S3, ACS_S7, ACS_LEQUAL, ACS_GEQUAL, ACS_PI, ACS_NEQUAL, ACS_STERLING }; char acs_name[][20] = { "ACS_ULCORNER", "ACS_LLCORNER", "ACS_URCORNER", "ACS_LRCORNER", "ACS_LTEE", "ACS_RTEE", "ACS_BTEE", "ACS_TTEE", "ACS_HLINE", "ACS_VLINE", "ACS_PLUS", "ACS_S1", "ACS_S9", "ACS_DIAMOND", "ACS_CKBOARD", "ACS_DEGREE", "ACS_PLMINUS", "ACS_BULLET", "ACS_LARROW", "ACS_RARROW", "ACS_DARROW", "ACS_UARROW", "ACS_BOARD", "ACS_LANTERN", "ACS_BLOCK", "ACS_S3", "ACS_S7", "ACS_LEQUAL", "ACS_GEQUAL", "ACS_PI", "ACS_NEQUAL", "ACS_STERLING" }; int rows = 5, page=0, i, j, flag=0; int acs_nr = sizeof(acs_symbol) / sizeof(chtype); for(j=0; j<=acs_nr/rows; j++) { clear (); for(i=0; i<rows; i++) { if(page*rows+i <= acs_nr-1) { mvaddch(i*2+1, 3, acs_symbol[page*rows + i]); mvaddstr(i*2+1, 8, acs_name[page*rows + i]); } else { flag=1; } } if(!flag) { mvaddstr(rows*2 +2, 1, "Taste drücken -> nächste Seite"); } else { mvaddstr(rows*2 +2, 1, "Taste drücken -> Ende"); } refresh(); page++; getch(); } } void quit(void) { endwin(); } int main(void) { initscr(); atexit(quit); noecho(); curs_set(0); write_pages(); return(0); }
Fenster löschen
BearbeitenDer durch ein Fenster belegte Speicherplatz kann über die Funktion
int delwin(WINDOW *win);
wieder freigegeben werden. Auf die Bildschirmdarstellung hat das vorerst keinen Einfluss. Natürlich sollte danach nicht mehr auf das gelöschte Fenster zugegriffen werden, da dies in aller Regel einen Programmabsturz infolge "Speicherzugriffsfehler" auslöst.
Fenster refreshen
BearbeitenZum Refreshen eines Fensters sind diese Funktionen vorgesehen:
int wrefresh(WINDOW *win); int wnoutrefresh(WINDOW *win); int doupdate(void);
Welche Funktion soll wann Verwendung finden?
Die einfachste Möglichkeit ist der Aufruf von wrefresh
. Diese Funktion bringt den gewünschten Fensterinhalt auf den real existierenden Bildschirm. wrefresh
besteht im Prinzip aus der sequentiellen Abfolge der Funktionen:
wnoutrefresh
... kopiert den gewünschten Fensterinhalt in den virtuellen Bildschirmspeicher.doupdate
... gleicht virtuellen Bildschirmspeicher mit dem realen Bildschirminhalt ab und vollzieht das Update.
Sind viele Fenster gleichzeitig zu refreshen, dann ist die wrefresh
-Funktion ineffizient. In diesem Fall ist es besser, zuerst alle Fenster mit einem wnoutrefresh
zu aktualisieren und am Ende nur einmal die doupdate
-Funktion aufzurufen.
Touch und Untouch
BearbeitenWird der Fensterinhalt geändert, dann wird das Fenster automatisch als "touched" (berührt) markiert. Die refresh-Funktion erkennt daran, dass das Fenster aktualisiert werden muss. Als "untouched" markierte Fenster werden bei Refreshs nicht aktualisiert, da aus Performancegründen virtueller und physikalischer Screen abgeglichen und nur die Änderungen übertragen werden. Ein Fenster kann auch manuell wieder als "untouched" markiert werden.
int touchwin(WINDOW *win); int untouchwin(WINDOW *win); bool is_wintouched(WINDOW *win);
Beispiel
Bearbeiten
<<< ncurses-Startseite | ncurses | << Inhaltsverzeichnis |
< Spezialtasten | Panels > |