Книга: Основы программирования в Linux

Перемещение и обновление окна

Перемещение и обновление окна

Следующие команды позволят вам перемещать и перерисовывать окна:

#include <curses.h>
int mvwin(WINDOW *window_to move, int new_y, int new x);
int wrefresh(WINDOW *window_ptr);
int wclear(WINDOW *window_ptr);
int werase(WINDOW *window_ptr);
int touchwin(WINDOW *window_ptr);
int scrollok(WINDOW *window_ptr, bool scroll_flag);
int scroll(WINDOW *window_ptr);

Функция mvwin перемещает окно по экрану. Поскольку окно целиком должно располагаться в области экрана, функция mvwin завершится аварийно, если вы попытаетесь переместить окно так, что какая-то его часть выйдет за пределы экрана.

Функции wrefresh, wclear и werase — просто обобщения функций, с которыми вы встречались ранее; они только принимают указатель WINDOW, поэтому могут ссылаться на конкретное окно, а не на окно stdscr.

Функция touchwin довольно специальная. Она информирует библиотеку curses о том, что содержимое окна, на которое указывает ее параметр, было изменено. Это означает, что curses всегда будет перерисовывать такое окно при следующем вызове функции wrefresh, даже если вы на самом деле не меняли содержимое этого окна. Эта функция очень полезна для определения отображаемого окна при наличии нескольких перекрывающихся окон, загромождающих экран.

Две функции scroll управляют прокруткой окна. Функция scrollok при передаче логического значения true (обычно ненулевого) включает прокрутку окна. По умолчанию окна не прокручиваются. Функция scroll просто прокручивает окно на одну строку вверх. В некоторые реализации библиотеки curses входит и функция wsctl, которая также принимает количество строк для прокрутки, которое может быть и отрицательным числом. Мы вернемся к прокрутке немного позже в этой главе.

А теперь выполните упражнение 6.4.

Упражнение 6.4. Управление множественными окнами

Теперь, зная, как управлять несколькими окнами, вы можете включить эти новые функции в программу multiw1.c. Для краткости проверка ошибок не приводится.

1. Как обычно, вставьте первыми отсортированные объявления:

#include <unistd.h>
#include <stdlib.h>
#include <curses.h>
int main() {
 WINDOW *new_window_ptr;
 WINDOW *popup_windov_ptr;
 int x loop;
 int y_loop;
 char a_letter = 'a';
 initscr();

2. Заполните базовое окно символами, обновляя физический экран, когда заполнен логический экран:

 move(5, 5);
 printw("%s", "Testing multiple windows");
 refresh();
 for (y_loop = 0; y_loop < LINES - 1; y_loop++) {
  for (x_loop = 0; x_loop < COLS - 1; x_loop++) {
   mvwaddch(stdscr, y_loop, x_loop, a_letter);
   a_letter++;
   if (a_letter > 'z') a_letter = 'a';
  }
 }
 /* Обновление экрана */
 refresh();
 sleep(2);

3. Теперь создайте окно 10?20 и вставьте в него текст перед прорисовкой окна на экране:

 new_window_ptr = newwin(10, 20, 5, 5);
 mvwprintw(new_window_ptr, 2, 2, "%s", "Hello World");
 mwwprintw(new_window_ptr, 5, 2, "%s",
  "Notice how very long lines wrap inside the window");
 wrefresh(new_window_ptr);
 sleep(2);

4. Измените содержимое фонового окна. Когда вы обновите экран, окно, на которое указывает new_window_ptr, будет затемнено:

 a_letter = '0';
 for (y_lоор = 0; y_lоор < LINES - 1; y_lоор++) {
  for (х_lоор = 0; xloop < COLS - 1; х_lоор++) {
   mvwaddch(stdscr, y_loop, х_lоор, a_letter);
   a_letter++;
   if (a_letter > '9') a_letter = '0';
  }
 }
 refresh();
 sleep(2);

5. Если вы выполните вызов для обновления нового окна, ничего не изменится, поскольку вы не изменяли новое окно:

 wrefresh(new_window_ptr);
 sleep(2);

6. Но если вы сначала воспользуетесь функцией touchwin и заставите библиотеку curses думать, что окно было изменено, следующий вызов функции wrefresh снова отобразит новое окно на переднем плане.

 touchwin(new_window_ptr);
 wrefresh(new_window_ptr);
 sleep(2);

7. Добавьте еще одно накладывающееся окно с рамкой вокруг него.

 popup_window_ptr = newwin(10, 20, 8, 8);
 box(popup_window_ptr, '|', '-');
 mvwprintw(popup_window_ptr, 5, 2, "%s", "Pop Up Window!");
 wrefresh(popup_window_ptr);
 sleep(2);

8. Поиграйте с новыми всплывающими окнами перед их очисткой и удалением.

 touchwin(new_window_ptr);
 wrefresh(new_window_ptr);
 sleep(2);
 wclear(new_window_ptr);
 wrefresh(new_window_ptr);
 sleep(2);
 delwin(new_window_ptr);
 touchwin(popup_window_ptr);
 wrefresh(popup_window_ptr);
 sleep(2);
 delwin(popup_window_ptr);
 touchwin(stdscr);
 refresh();
 sleep(2);
 endwin();
 exit(EXIT_SUCCESS);
}

К сожалению, нет возможности продемонстрировать выполнение этого фрагмента в книге, но на рис. 6.4 показан снимок экрана после отображения первого всплывающего окна.


Рис. 6.4

После того как будет изменен фон и появится новое всплывающее окно, вы увидите экран, показанный на рис. 6.5.


Рис. 6.5

Как это работает

После обычной инициализации программа заполняет стандартный экран цифрами, чтобы легче было увидеть новые окна, вставляемые на передний план. Далее показано, как можно наложить на фон новое окно с включенным в него текстом, разбитым на строки в соответствии с шириной окна. Далее вы видите, как с помощью функции touchwin заставить curses перерисовать окно, даже если в нем ничего не менялось.

Затем перед закрытием curses и завершением программы вставляется второе окно, перекрывающее первое, чтобы показать, как библиотека curses может управлять перекрывающимися окнами.

Как видно из программного кода примера, при обновлении окон следует быть очень внимательным, чтобы они отображались в нужной очередности. Библиотека curses не хранит никаких сведений об иерархии окон, поэтому если вы попросите curses обновить несколько окон, управлять их иерархией придется вам.

Примечание

Для того чтобы библиотека curses отображала окна в нужном порядке, их следует обновлять в этом порядке. Один из способов добиться этого — сохранять все указатели ваших окон в массиве или списке, в которых поддерживается порядок их размещения, соответствующий порядку их появления на экране.

Оглавление книги


Генерация: 5.616. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз