====== Программирование в X-Window средствами Free Pascal ====== [[index|Перейти к содержанию]] ===== 1.1.9. Операции над окнами ===== Манипулировать окнами можно не только с помощью атрибутов: Xlib предоставляет набор функций для изменения их размеров, перемещения на экране и в стеке окон, сворачивания и т.п. Первая пара операций, которые можно применить к окну - отображение или скрытие. Отображение окна заставляют окно появиться на экране, скрытие приводит к удалению с экрана (хотя логическое окно в памяти все еще существует). Например, если в вашей программе есть диалоговое окно, вместо создания его каждый раз по запросу пользователя, мы можем создать окно один раз в скрытом режиме и, когда пользователь запросит открыть диалог, просто отобразить окно на экране. Когда пользователь нажимает "''OK''" или "''Cancel''", окно скрывается. Это значительно быстрее создания и уничтожения окна, однако стоит ресурсов, как на стороне клиента, так и на стороне X сервера. Отображение окна может быть выполнено с помощью ''XMapWindow()'', скрытие - с помощью ''XUnmapWindow()''. Функция отображения заставит событие ''Expose'' послаться программе, если только окно полностью не закрыто другими окнами. Другое действие, которое можно выполнить над окнами - переместить их в другую позиции. Это может быть выполнено функцией ''XMoveWindow()'', которая принимает новые координаты окна. Имейте в виду, что после перемещения окно может быть частично скрытым другими окнами (или наоборот, открыто ими), и таким образом, может быть сгенерировано сообщение ''Expose''. Изменить размер окна можно с помощью функции ''XResizeWindow()''. Мы можем также объединить перемещение и изменение размеров, используя одну функцию ''XMoveResizeWindow()''. Все приведенные выше функции изменяли свойства одного окна. Существует ряд свойств, связанных с данным окном и другими окнами. Одно из них - порядок засылки в стек: порядок, в котором окна располагаются друг над другом. Говорят, что окно переднего плана находится на верхе стека, а окно заднего плана - на дне стека. Перемещение окна на вершину стека осуществляет функция ''XRaiseWindow()'', перемещение окна на дно стека - функция ''XLowerWindow()''. С помощью функции ''XIconifyWindow()'' окно может быть свернуто, а с помощью ''XMapWindow()'' - восстановлено. Для того, чтобы понять, почему для ''XIconifyWindow()'' нет обратной функции, необходимо заметить, что, когда окно сворачивается, на самом деле оно скрывается, а вместо него отображается окно иконки. Таким образом, чтобы восстановить исходное окно, нужно просто отобразить его снова. Иконка является на самом деле другим окном, которое просто тесно связано сильно с нашим нормальным окном - это не другое состояние нашего окна. Следующий пример демонстрирует использование операций над окнами: uses x,xlib,xutil,crt,dos; (* create_simple_window - создает окно с белым фоном заданного размера. Принимает в качестве параметров дисплей, размер окна (в пикселях) и положение окна (также в пикселях). Возвращает дескриптор окна. Окно создается с черной рамкой шириной в 2 пикселя и автоматичсеки отображается после создания. *) function create_simple_window(display : PDisplay; width, height, x, y : integer): TWindow; var screen_num, win_border_width: integer; win: TWindow; begin screen_num := XDefaultScreen(display); win_border_width := 2; (* создаем простое окно как прямой потомок корневого окна экрана, используя черный и белый цвета в качестве основного и фонового, и размещая новое окно в верхнем левом углу по заданным координатам *) win := XCreateSimpleWindow(display, XRootWindow(display, screen_num), x, y, width, height, win_border_width, XBlackPixel(display, screen_num), XWhitePixel(display, screen_num)); (* Отображаем окно на экране. *) XMapWindow(display, win); (* Заставляем выполниться все запросы к Х серверу. *) XFlush(display); create_simple_window:=win; end; //void main(int argc, char* argv[]) var display: PDisplay; (* указатель на структуру дисплея Х *) screen_num: integer; (* количество экранов для размещения окон *) win: TWindow; (* дескриптор создаваемого окна *) display_width, display_height: word; (* высота и ширина Х дисплея *) win_width, win_height: word; (* высота и ширина нового окна *) display_name: array [0..30] of Char; name: string; i: integer; win_attr: TXWindowAttributes; xx, y, scr_x, scr_y: integer; child_win: TWindow; (* переменная для хранения дескриптора родительского окна *) parent_win: TWindow; (* эта переменная будет хранить дескриптор корневого окна *) (* экрана, на котором отображено наше окно *) root_win: TWindow; (* эта переменная будет хранить массив дескрипторов *) (* дочерних окон нашего окна, *) child_windows: PWindow; (* а эта - их количество *) num_child_windows: integer; begin name := getenv('DISPLAY'); (* имя Х дисплея *) for i:=1 to byte(name[0]) do display_name[i-1]:=name[i]; display_name[byte(name[0])]:=#0; (* устанавливаем соединение с Х сервером *) display := XOpenDisplay(display_name); if (display = NIL) then begin writeln(paramstr(0),': не могу соединиться с Х сервером ', display_name); halt(1); end; (* получаем геометрию экрана по умолчанию для нашего дисплея *) screen_num := XDefaultScreen(display); display_width := XDisplayWidth(display, screen_num); display_height := XDisplayHeight(display, screen_num); (* создаем новое окно в 1/9 площади экрана *) win_width := (display_width div 3); win_height := (display_height div 3); (* отладочная печать в стандартный вывод *) writeln('ширина окна - ', win_width, '; высота - ', win_height); (* создаем простое окно как прямой потомок корневого окна экрана, *) (* используя черный и белый цвета в качестве основного и фонового, и*) (* размещая новое окно в верхнем левом углу по заданным координатам *) win := create_simple_window(display, win_width, win_height, 0, 0); XFlush(display); (* отдохнем после трудов праведных *) delay(3000); (* пример изменения размеров окна *) begin (* в цикле уменьшаем окно *) for i:=0 to 39 do begin dec(win_width,3); dec(win_height,3); XResizeWindow(display, win, win_width, win_height); XFlush(display); delay(20); end; (* в цикле увеличиваем окно *) for i:=0 to 39 do begin inc(win_width,3); inc(win_height,3); XResizeWindow(display, win, win_width, win_height); XFlush(display); delay(20); end; end; delay(1000); (* пример перемещения окна *) begin (* вначале получаем текущие атрибуты окна *) XGetWindowAttributes(display, win, @win_attr); xx := win_attr.x; y := win_attr.y; (* затем находим окно родителя *) begin (* выполним запрос необходимых значений *) XQueryTree(display, win, @root_win, @parent_win, @child_windows, @num_child_windows); (* мы должны освободить список дочерних дескрипторов, *) (* так как он был динамически выделен XQueryTree() *) XFree(child_windows); end; (* Транслируем локальные координаты в экранные, используя *) (* корневое окно как окно, относительно которого выполняется *) (* трансляция. Это работает потому, что корневое окно всегда *) (*занимает весь экран, и его левый верхний угол совпадает *) (* с левым верхним углом экрана *) XTranslateCoordinates(display, parent_win, win_attr.root, xx, y, @scr_x, @scr_y, @child_win); (* перемещаем окно влево *) for i:=0 to 39 do begin dec(scr_x,3); XMoveWindow(display, win, scr_x, scr_y); XFlush(display); delay(20); end; (* перемещаем окно вниз *) for i:=0 to 39 do begin inc(scr_y,3); XMoveWindow(display, win, scr_x, scr_y); XFlush(display); delay(20); end; (* перемещаем окно вправо *) for i:=0 to 39 do begin inc(scr_x,3); XMoveWindow(display, win, scr_x, scr_y); XFlush(display); delay(20); end; (* перемещаем окно вверх *) for i:=0 to 39 do begin dec(scr_y,3); XMoveWindow(display, win, scr_x, scr_y); XFlush(display); delay(20); end; end; delay(1000); (* пример сворачивания и восстановления окна *) begin (* сворачиваем окно *) XIconifyWindow(display, win, XDefaultScreen(display)); XFlush(display); delay(2000); (* восстанавливаем окно *) XMapWindow(display, win); XFlush(display); delay(2000); end; XFlush(display); (* короткая передышка *) delay(2000); (* закрываем соединение с Х сервером *) XCloseDisplay(display); end. Приложение:\\ Исходный код программы [[http://www.sources.ru/pascal/graph/xwinfpc/winmove.zip|winmove.pas]]