А. Полищук - Программирование в X Window средствами Free Pascal
Все приведенные выше функции изменяли свойства одного окна. Существует ряд свойств, связанных с данным окном и другими окнами. Одно из них - порядок засылки в стек: порядок, в котором окна располагаются друг над другом. Говорят, что окно переднего плана находится на верхе стека, а окно заднего плана - на дне стека. Перемещение окна на вершину стека осуществляет функция 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.
1.1.10 Лабораторная работа #1 "Основные понятия Xlib"
1. Используя компилятор командной строки, выполните компиляцию примера из п. 1.1 и выполните полученную программу.
2. Настройте интегрированную среду Анюта для работы с кириллицей и выполните компиляцию в ней предыдущей программы.
3. На основе примера напишите программу, которая при нажатии клавиши мыши пишет сообщение Pressed, а при отпускании - Released.
4. Используя функции XFlush() / XSync() и delay(), напишите программу без цикла обработки сообщений, отображающую черное окно размером 100х100 пикселей в течение 5 секунд.