Программирование в X-Window средствами Free Pascal

Перейти к содержанию

1.2.6. Изменение формы мышиного курсора

Программы часто модифицируют форму указателя мыши (также называемого указателем X) в зависимости от своего состояния. Например, занятое приложение часто отображает над своим основным окном песочные часы, чтобы дать пользователю визуальный намек, что он должен ожидать. Без такого визуального намека пользователь мог бы подумать, что приложение зависло.

Есть два основных метода создания курсоров. Первый из них - использование набора предопределенных курсоров, поставляемых с Xlib. Второй - использование битовых изображений, определенных пользователем.

В первом методе используется специальный шрифт «cursor» и функция XCreateFontCursor(). Эта функция принимает идентификатор формы, и возвращает дескриптор на созданный курсор. Список возможных шрифтовых идентификаторов находится в файле /usr/include/X11/cursorfont.h. Всего их более 70; вот некоторые из таких курсоров:

Создать курсор с использованием этих идентификаторов несложно. Из файла /usr/include/X11/cursorfont.h узнаем номера необходимых идентификаторов и опеределяем их:

const 
  XC_watch=150;
 
var
  (* эта переменная содержит дескриптор создаваемого курсора *) 
  watch_cursor : TCursor;
 
  (* создаем курсор "песочные часы" *)
  watch_cursor := XCreateFontCursor(display, XC_watch);

Другой метод создания курсора - использование пары пиксельных карт глубиной 1. Одна пиксельная карта определяет форму курсора, а другая работает как маска, определяющая, какие пиксели курсора действительно будут нарисованы. Остальная часть пикселей будет прозрачной. Создание такого курсора осуществляется с помощью функции XCreatePixmapCursor().
В качестве примера создадим курсор, используя битовое изображение «icon.bmp». Будем предполагать, что оно уже загружено в память и преобразовано в пиксельную карту, дескриптор которой сохранен в переменной bitmap. Мы хотим, что оно было полностью прозрачным. Это означает, что только черные фрагменты нарисуются, а белые будут прозрачными. Чтобы достигнуть такого эффекта, будем использовать иконку и как пиксельную карту курсора, и как маску пиксельной карты.

var
  (* эта переменная содержит дескриптор создаваемого курсора *)
  icon_cursor : TCursor;
 
  (* вначале необходимо определить основной и фоновый цвета курсора *)
  cursor_fg, cursor_bg : TXColor;
 
  screen_colormap : TColormap;
  rc : TStatus;
 
  (* получаем доступ к палитре экрана по умолчанию *)
  screen_colormap := XDefaultColormap(display, XDefaultScreen(display));
 
  (* выделяем черный и белый цвета *)
  rc := XAllocNamedColor(display,
               screen_colormap,
               'black',
               @cursor_fg,
               @cursor_fg);
  if (rc = 0) then begin
    writeln('XAllocNamedColor - невозможно распределить цвет "black"');
    halt(1);
  end;
  rc := XAllocNamedColor(display,
               screen_colormap,
               'white',
               @cursor_bg,
               @cursor_bg);
  if (rc = 0) then begin
    writeln('XAllocNamedColor - невозможно распределить цвет "white"');
    halt(1);
  end;
 
  (* Наконец, создаем курсор. Горячую точку устанавливаем ближе к *)
  (* верхнему левому углу курсора - позиции (x=5, y=4). *)
  icon_cursor := XCreatePixmapCursor(display, bitmap, bitmap,
                 @cursor_fg, @cursor_bg,
                 5, 4);

Когда мы определяем курсор, необходимо определить, какой пиксель курсора является указателем, доставляемым пользователю в различные события от мыши. Обычно, мы выберем позицию курсора, которая визуально выглядит похожей на «горячую точку». Например, на курсоре в виде стрелки конец стрелки будет определен как горячая точка.

Когда курсор больше не нужен, его необходимо освободить, используя функцию XFreeCursor():

XFreeCursor(display, icon_cursor);

После того, как курсор создан, необходимо сообщить X серверу об окне, к которому он должен быть подключен. Это делается с помощью XDefineCursor(), и заставляет сервер X менять указатель мыши на форму этого курсора всякий раз, когда указатель мыши перемещается внутри этого окно. Мы можем отключить этот курсор от нашего окна с помощью функции XUndefineCursor(), которая заставит отображаться встроенный курсор.

(* прикрепить курсор к окну *)
XDefineCursor(display, win, icon_cursor);
 
(* отключить курсор от окна *)
XUndefineCursor(display, win);