Современная электронная библиотека ModernLib.Net

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

ModernLib.Net / Программирование / Полищук А. / Программирование в X Window средствами Free Pascal - Чтение (стр. 4)
Автор: Полищук А.
Жанр: Программирование

 

 


      Есть два основных метода создания курсоров. Первый из них - использование набора предопределенных курсоров, поставляемых с Xlib. Второй - использование битовых изображений, определенных пользователем.
      В первом методе используется специальный шрифт "cursor" и функция XCreateFontCursor(). Эта функция принимает идентификатор формы, и возвращает дескриптор на созданный курсор. Список возможных шрифтовых идентификаторов находится в файле /usr/include/X11/cursorfont.h. Всего их более 70; вот некоторые из таких курсоров:
      • XC_arrow - обычный курсор в форме стрелки, отображаемый сервером.
      • XC_pencil - курсор в форме карандаша.
      • XC_watch - песочные часы.
      Создать курсор с использованием этих идентификаторов несложно. Из файла /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 менять указатель мыши на форму этого курсора всякий раз, когда указатель мыши перемещается внутри этого окно. Мы можем отключить этот курсор от нашего окна с помощью функции Xlib XUndefineCursor(), которая заставит отображаться встроенный курсор.
       (* прикрепить курсор к окну *)
       XDefineCursor(display, win, icon_cursor);
 
       (* отключить курсор от окна *)
       XUndefineCursor(display, win);

1.2.7 Лабораторная работа #2 "Текст и графика"

      1. Напишите программу, выводящую текстовое сообщение в произвольную позицию (в пределах окна) произвольным цветом. Цвет и координаты должны меняться при изменении размеров окна.
 
      2. Составьте программу, принимающую со стандартного ввода маску шрифта, выводимую строку, координаты х, у и отображающую окно с текстом согласно введенной информации.
 
      3. Нарисуйте в окне график функции sin(x) на отрезке [-?;?]. Оси подпишите курсивом, метки по осям - обычным шрифтом, начало координат (0) выделите жирным шрифтом.
 
      4. Нарисуйте в окне 100 окружностей. Цвет, координаты центра и радиус выбирать случайным образом.
 
      5. Используя StructureNotifyMask и русский шрифт, модифицируйте программу из первого задания лабораторной работы #1 таким образом, чтобы сообщение всегда отображалось в центре окна.
 
      6. Составьте программу, выводящую в окно все символы стандартного курсорного шрифта.

1.3 Работа с внешними устройствами

1.3.1 Клавиатура

      Как и большинство интерактивных программ, задачи, выполняющиеся в X Window, активно используют для ввода информации клавиатуру компьютера. Когда пользователь нажимает или отпускает клавишу, сервер получает соответствующий сигнал, который преобразуется в событие и отправляется в очередь программы, имеющей фокус ввода (input focus).
      Поясним, что такое фокус ввода. Дело в том, что клавиатура у машины одна, и она разделяется всеми выполняющимися одновременно программами. Но в каждый момент времени поступающий от устройства сигнал доступен лишь одной из них, как правило, той, которой принадлежит активное окно. В этом случае говорят, что программа и ее окно имеют фокус ввода. Последний может переходить от окна к окну и от программы к программе.
      Когда окно получает фокус, соответствующей программе посылается событие FocusIn, при потере - приходит событие FocusOut.
      Когда пользователь нажимает клавишу клавиатуры, программа получает событие KeyPress. Сервер также может послать событие KeyRelease, когда клавиша отпускается, но это справедливо не для всех типов компьютеров.
      Оба этих события сопровождаются структурой типа TXKeyEvent. Ее поле keycode содержит код нажатой клавиши, а поле state - состояние клавиш-модификаторов и кнопок мыши. Модификаторами называются такие клавиши, как Shift, Ctrl, Caps Lock. Кроме этого, X предусматривает наличие дополнительных модификаторов, которые обозначаются Mod1,…, Mod5. Каждой нажатой клавише-модификатору и кнопке мыши соответствует флаг в поле state.
      Коды, передаваемые через поле keycode структуры TXKeyEvent, однозначно идентифицируют клавиши. Их конкретные значения зависят от типа машины и клавиатуры. Эти коды мы будем называть физическими. Чтобы обеспечить переносимость программ, сервер устанавливает соответствие между физическими кодами клавиш, которые могут меняться от компьютера к компьютеру, и целочисленными константами - логическими кодами (символами). Они имеют предопределенные значения, которые приведены в файле /usr/include/X11/keysymdef.h и начинаются с префикса "XK_". Так, букве "a" соответствует символ XK_a, клавише ‹Return› (‹Enter›) - символ XK_Return и т.д.
      Для разных алфавитов X поддерживает разные множества логических кодов. Возможные типы алфавитов перечисляются в файле /usr/include/X11/keysym.h.
      Одному коду клавиши может соответствовать несколько символов в зависимости от состояния клавиш-модификаторов. Функция
       function XKeycodeToKeysym(prDisplay: PDisplay; nKeycode: TKeyCode; nIndex: longint): TKeySym; cdecl; external;
      позволяет по коду nKeyCode получить соответствующий ему символ с номером nIndex. Если nIndex равен 0, то полученный символ соответствует просто нажатой клавише. Если nIndex равен 1, то возвращается символ, соответствующий ситуации, когда клавиша нажата одновременно с Shift.
      Функция XKeysymToKeycode() осуществляет обратное преобразование.
      Программа может получить карту соответствия кодов и символов, обратившись к процедуре XGetKeyboardMapping().
      Изменяется соответствие физических и логических кодов процедурой XChangeKeyboardMapping(). Следующая последовательность операторов ставит клавише ‹F2› в соответствие символ XK_F3.
      …
       var
        nF2Sym, nF3Sym: TKeysym;
        nF2Keycode: TKeyCode;
        prDisplay: PDisplay;
      …
        nF2Sym:= XStringToKeysym ('F2');
        nF3Sym:= XStringToKeysym ('F3');
        nF2Keycode:= XKeysymToKeycode (prDisplay, nF2Sym);
        XChangeKeyboardMapping (prDisplay, nF2Keycode, 1, @nF3Sym, 1);
      …
      Здесь использована процедура XStringToKeysym(), которая по строке "str" возвращает соответствующий символ XK_str.
      Когда соответствие кодов меняется, всем работающим в настоящее время клиентам посылается событие MappingNotify.
      Клавиши-модификаторы также имеют логические коды. Клавишам Shift сопоставлены символы XK_Shift_L и XK_Shift_R; Caps Lock соответствует XK_CapsLock; Control - XK_Control_L; Mod1 - XK_Meta_L и XK_Meta_R. Символы остальных модификаторов (Mod2 - Mod5) не определены. X содержит набор специальных процедур, которые позволяют получить и установить соответствие код-символ для модификаторов. Эти функции следующие: XGetModifierMapping(), XInsertModifiermapEntry(), XDeleteModifiermapEntry(), XSetModifierMapping().
      X не останавливается на задании соответствия код клавиши - символы, а идет дальше. Система позволяет программе сопоставить любой комбинации модификаторов и клавиш (например, ‹Shift+Ctrl+A›) ASCII строку (например, "EXIT"). Для некоторых клавиш соответствующие строки задаются сервером по умолчанию. Так, символу XK_A соответствует строка "A".
      Макрос XRebindKeysym() берет символ, список модификаторов и сопоставляет им строку.
      Процедура XLookupString(), наоборот, берет событие о нажатии (отпускании) клавиши и возвращает соответствующие ему символ и строку. Последний ее параметр - указатель на структуру типа XComposeStatus. Дело в том, что некоторые клавиатуры имеют специальную клавишу Compose, которая позволяет печатать символы, которым нет соответствия среди клавиш. Специальная таблица указывает, какой символ должен быть создан, если обычная клавиша нажимается одновременно с Compose. Ссылка на эту информацию и возвращается в структуре XComposeStatus.
      Ниже приводится фрагмент программы, которая распознает функциональные клавиши ‹F1›-‹F5›, и при их нажатии печатает соответствующую строку. Программа также сопоставляет комбинации ‹Shift+Control+A› строку "EXIT". Эта комбинация используется для завершения программы.
      …
       var
        prDisplay: PDisplay;
        nScreenNum: integer;
        prGC: TGC;
        rEvent: TXEvent;
        nWnd: TWindow;
        sKeyStr: array [0…19] ofchar;
        nKeySym: TKeySym;
        naModList: array [0…1] ofTKeySym;
        n: integer;
        r: char;
 
       const
        XK_Control_L=$FFE3; (* Left control *)
        XK_Shift_L=$FFE1; (* Left shift *)
        XK_F1=$FFBE;
        XK_F2=$FFBF;
        XK_F3=$FFC0;
        XK_F4=$FFC1;
        XK_F5=$FFC2;
        XK_F6=$FFC3;
 
        (* Устанавливаем связь с сервером, получаем номер экрана… *)
      …
        (* Задаем соответствие символ-строка *)
        naModList[0]:= XK_Control_L;
        naModList[1]:= XK_Shift_L;
        XRebindKeysym (prDisplay, XK_F6, naModList, 2, 'EXIT', strlen('EXIT'));
        (* Цикл получения и обработки событий *)
        while true do begin
         XNextEvent (prDisplay, @rEvent);
         case (rEvent.eventtype) of
      …
         KeyPress:
         begin
          (* Очищаем строку *)
          for n:=0 to 19 do  sKeyStr[n]:=#0;
 
          (* Получаем строку, соответствующую событию *)
          XLookupString (@rEvent.xkey, sKeyStr, 20, @nKeySym, NIL);
          if (strcomp (sKeyStr, 'EXIT')=0) then
          begin
           XFreeGC (prDisplay, prGC);
           XCloseDisplay (prDisplay);
           halt (0);
          end;
 
          case nKeySym of
          XK_F1: r:='1';
          XK_F2: r:='2';
          XK_F3: r:='3';
          XK_F4: r:='4';
          XK_F5: r:='5';
          else r:='0';
          end;
 
          if (n<>0) then begin
           sKeyStr[0]:='F';
           sKeyStr[1]:=r;
           sKeyStr[2]:=#0;
           strcat(sKeyStr, ' pressed.');
           XClearWindow (prDisplay, nWnd);
           XDrawString (prDisplay, nWnd, prGC, 10, 50, sKeyStr, strlen (sKeyStr));
          end;
         end;
        end;
       end;
      …
      Сервер имеет ряд атрибутов, воздействующих на обработку сигналов клавиатуры. Получить их можно с помощью функции XGetKeyboardControl(). Она возвращает указанные параметры в переменной, имеющей тип TXKeyboardState, определенный следующим образом:
       TXKeyboardControl = record
        key_click_percent: longint;
        bell_percent: longint;
        bell_pitch: longint;
        bell_duration: longint;
        led: longint;
        led_mode: longint;
        key: longint;
        auto_repeat_mode: longint;
        end;
       PXKeyboardControl = ^TXKeyboardControl;
      Первые четыре поля совпадают с аналогичными полями структуры TXKeyboardState. Поля led и led_mode позволяют сообщить серверу, какие из клавиш-модификаторов должны сопровождаться подсветкой. Если поле led не задано, и led_mode равно LedModeOn, то изменяется состояние всех клавиш, для которых поддерживается световое сопровождение. Если led_mode равно LedModeOff, то состояние клавиш не меняется. Если поле led задано, то это есть комбинация флагов, указывающих, для каких клавиш подсветку включить (led_mode равно LedModeOn) или выключить (led_mode равно LedModeOff).
      Поля key и auto_repeat_mode определяют, для какой клавиши (клавиш) включить (auto_repeat_mode равно AutoRepeatModeOn) или выключить (auto_repeat_mode равно AutoRepeatModeOff) режим автоматического повтора. Если поле key задано, то автоматический повтор включается или выключается только для клавиши с кодом key.

1.3.2 Мышь

      С точки зрения программы общение с мышью похоже на работу с клавиатурой. X получает сигналы от устройства, преобразует их в события и помещает последние в очередь программы. Однако есть и существенная разница. Если события от клавиатуры передаются лишь программе, окно которой имеет фокус ввода, то события от мыши могут передаваться, в принципе, любой задаче, окно (окна) которой присутствуют на экране.
      Чаще всего приходится обрабатывать события нажатия (отпускания) кнопки мыши. Для регистрации такого типа событий, необходимо добавить одну из следующих масок с помощью функции XSelectInput():
      • ButtonPressMask - уведомлять о нажатии любой кнопки в одном из окон программы.
      • ButtonReleaseMask - уведомлять об отпускании любой кнопки в одном из окон программы.
      В цикле обработки сообщений могут проверяться такие события:
      • ButtonPress - нажата кнопка в одном из окон программы.
      • ButtonRelease - отпущена кнопка в одном из окон программы.
      Структура для этих сообщений получается доступом к полю xbutton объединения TXEvent и содержит, в частности, такие поля:
      • window: TWindow - идентификатор окна, которому было послано сообщение (в случае, если оно было зарегистрировано для нескольких окон программы).
      • x, y: longint - координаты x и y (в пикселях) мышиного курсора в момент нажатия.
      • button: cardinal - номер нажатой кнопки (может принимать значения Button1, Button2, Button3).
      • time: TTime - время (в миллисекундах), которое длилось событие. Может использоваться для определения "двойного щелчка".
      В качестве примера приведем фрагмент кода, в котором рисуется черный пиксель в позиции мыши всякий раз, когда мы получаем событие "нажатие кнопки" от первой кнопки мыши, и стирается пиксель (то есть рисуется белый), когда нажата вторая кнопка мыши. Предполагается существование двух GC: gc_draw с черным цветом переднего плана и gc_erase с белым цветом переднего плана.
      …
       ButtonPress:
        begin
        (* сохраняем координаты кнопки мыши в целых переменных *)
        (* также сохраняем идентификатор окна, в котором была  нажата кнопка мыши *)
        x:= an_event.xbutton.x;
        y:= an_event.xbutton.y;
        the_win:= an_event.xbutton.window;
 
        (* проверяем, какая из кнопок была нажата,  и действуем соответственно *)
        case (an_event.xbutton.button) of
        Button1:
         (* рисуем пиксель в позиции мыши *)
         XDrawPoint(display, the_win, gc_draw, x, y);
        Button2:
         (* стираем пиксель в позиции мыши *)
         XDrawPoint(display, the_win, gc_erase, x, y);
        else (* возможно, третья кнопка - игнорируем *)
         ;
        end;
       end;
      …
      Подобно событиям нажатия и отпускания кнопки мыши, нас также могут извещать о различных событиях перемещения мыши. Они делятся на два семейства. Первое - перемещение указателя мыши, пока никакие кнопки не нажимаются, и второе - движение указателя мыши при одной (или более) нажатых кнопках (это иногда называется операцией "перетаскивания" (drag)). Следующие маски событий должны быть добавлено в вызов XSelectInput() для получения извещений о таких событиях:
      • PointerMotionMask - события указателя, перемещающегося в одном из окон программы, когда ни одна кнопка мыши не нажата.
      • ButtonMotionMask - события перемещения указателя, пока одна (или более) кнопок мыши удерживается нажатой.
      • Button1MotionMask - тоже, что и ButtonMotionMask, но только когда первая кнопка мыши удерживается нажатой.
      • Button2MotionMask, Button3MotionMask, Button4MotionMask, Button5MotionMask - аналогично для кнопок 2, 3, 4 или 5.
      В цикле обработки сообщений проверяется событие MotionNotify - указатель мыши перемещался в одном из окон, для которых мы запросили уведомление о таких событиях.
      Структура для этих сообщений получается доступом к полю xmotion объединения TXEvent и содержит, в частности, такие поля:
      • window: TWindow - идентификатор окна, которому было послано сообщение движения мыши (в случае, если оно было зарегистрировано для нескольких окон программы).
      • x, y: longint - координаты x и y (в пикселях) мышиного курсора в момент генерации сообщения.
      • state: cardinal - маска кнопок (или клавиш), удерживаемых во время этого события (если таковые имеются). Эта поле - побитовое "ИЛИ" любого из следующих значений: Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask, ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask. Первые пять значений ссылаются на кнопки мыши, которые нажимаются, остальные соответствуют различным специальным клавишам (Mod1 - обычно клавиша Alt или Meta).
      • time: TTime - время (в миллисекундах), которое длилось событие.
      Как пример, следующий код определяет режим рисования для графического редактора, в котором, если пользователь перемещает мышь, удерживая первую ее кнопку, мы рисуем на экране. Этот код имеет недостаток: поскольку перемещение мыши может генерировать много событий, вполне возможно, что мы не получим событие движения мыши для каждого пикселя, над которым проходит мышь. Один из способов разрещения этой ситуации состоит в запоминании последнего пикселя, над которым была "протащена" мышь, и рисованием линии между запомненной и новой позициями указателя мыши.
      …
        MotionNotify:
        begin
         (* сохраняем координаты кнопки мыши в целых переменных также сохраняем идентификатор окна, в котором была протащена мышь *)
         x:= an_event.xmotion.x;
         y:= an_event.xmotion.y;
         the_win:= an_event.xbutton.window;
 
         (* если первая кнопка мыши удерживалась во время этого события,  рисуем пиксель в позиции мышиного курсора *)
         if (an_event.xmotion.state AND Button1Mask) then begin
         XDrawPoint(display, the_win, gc_draw, x, y);
        end;
       end;
      …
      Другой тип мышиных событий - вход указателя мыши в окно программы или выход из окна. Некоторые программы используют эти события, чтобы показать пользователю, что приложение получило фокус. Для регистрации событий этого типа необходимо добавить одну (или более) из следующих масок в функции XSelectInput():
      • EnterWindowMask - уведомлять, когда указатель мыши входит в любое из окон программы.
      • LeaveWindowMask - уведомлять, когда указатель мыши выходит из окна программы.
      В цикле обработки сообщений проверяется одно из следующих событий:
      • EnterNotify - указатель мыши только что вошел в одно из окон программы.
      • LeaveNotify - указатель мыши только что вышел из окна программы.
      Структура для этих сообщений получается доступом к полю xcrossing объединения TXEvent и содержит, в частности, такие поля:
      • window: TWindow - идентификатор окна, которому было послано сообщение от мыши (в случае, если оно было зарегистрировано для нескольких окон программы).
      • subwindow: TWindow - идентификатор дочернего окна ребенка, из которого мышь перешла в текущее (в событии EnterNotify), или в которое указатель мыши переместился (в событии LeaveNotify), или None, если мышь переместилась за пределы окон программы.
      • x, y: longint - координаты x и y (в пикселях) мышиного курсора в момент генерации сообщения.
      • mode: longint - номер нажатой кнопки (может принимать значения Button1, Button2, Button3).
      • time: TTime - время (в миллисекундах), которое длилось событие. Может использоваться для определения "двойного щелчка".
      • state: cardinal - маска кнопок (или клавиш), удерживаемых во время этого события (если таковые имеются). Эта поле - побитовое "ИЛИ" любого из следующих значений: Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask, ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask. Первые пять значений ссылаются на кнопки мыши, которые нажимаются, остальные соответствуют различным специальным клавишам (Mod1 - обычно клавиша Alt или Meta).
      • focus: TBool - устанавливается в True, если окно имеет клавиатурный фокус, и False в противном случае.
      Обычно фокус ввода может свободно переходить от окна к окну. Но иногда программе необходимо запретить передачу фокуса. Это называется захватом клавиатуры. Для того, чтобы его реализовать, используется процедура XGrabKeyboard().
      Функция XGrabKey() запрещает передачу фокуса после нажатия определенной комбинации клавиш. Освободить клавиатуру можно, обратившись к процедуре XUngrabKeyboard() (XGrabKey()).
      Рассмотрим поведение системы при обработке событий от мыши. Как правило, если ее кнопка нажата в момент, когда ее курсор находится в неактивном окне, то последнее активизируется, и события от мыши передаются ему. Сказанное означает, что в нормальном состоянии окно получает только те события от мыши, которые соответствуют сигналам, пришедшим тогда, когда ее курсор находится в пределах окна. Но если программа вызывает
       function XGrabPointer(prDisplay: PDisplay; nGrabWnd: TWindow; nOwnerEvents: TBool; nEventMask: cardinal; nPointerMode: longint; nKeyboardMode: longint; nConfineTo: TWindow; nCursor: TCursor; nTime: TTime): longint; cdecl; external;
      то положение меняется. Теперь все события будут направляться окну с дескриптором nGrabWnd. Освобождается мышь вызовом XUngrabPointer(). Процедура XGrabButton() указывает, что курсор должен быть захвачен после нажатия определенной кнопки. Обратной к ней является процедура XUngrabButton().
      Процедуры, захватывающие устройство - мышь или клавиатуру - имеют ряд аргументов, влияющих на поведение системы.
      Так, параметр nConfineTo есть идентификатор окна, за пределы которого не должен выходить курсор мыши, если он захвачен.
      Если аргумент nOwnerEvents равен Тrue, то события мыши будут передаваться окнам программы. Если nOwnerEvents - False, или курсор находится в окне, не принадлежащем программе, то события мыши передаются окну nGrabWnd.
      Если nOwnerEvents равен False, то параметр nEventMask указывает, какие события следует передавать окну nGrabWnd.
      Обработка событий от клавиатуры или ныши может быть приостановлена, если nPointerMode или nKeyboardMode равен GrabModeSync. В этом случае события буферизуются сервером, пока устройство не будет освобождено с помощью XUngrabKeyboard(), XUngrabKey(), XUngrabPointer() или XUngrabButton().
      Параметр nCursor задает форму курсора во время того, как мышь захвачена. Аргумент nTime указывает, когда система должна активизировать режим захвата.

1.3.3 Лабораторная работа #3 "Работа с внешними устройствами"

      1. Используя функции XKeysymToString() и XKeycodeToKeysym(), напишите программу, которая реагирует на нажатие клавиш в окне выдачей в него кода символа, состояния модификаторов и символьной расшифровки нажатой клавиши.
 
      2. Напишите программу, определяющую координаты мыши в момент нажатия кнопки и печатающую в позицию мышиного курсора координаты мыши и номер нажатой кнопки.
 
      3. Модифицируйте предыдущую программу для рисования точек в местах нажатий мыши и при ее движении с нажатой кнопкой.
 
      4. Модифицируйте предыдущую программу для рисования отрезков между нажатиями мыши и при ее движении с нажатой кнопкой.
 
      5. Создайте программу, отображающую в окне содержимое текстового файла, имя которого задается в командной строке. Для скроллинга текста используйте клавиши Up, Down, Left, Right, PageUp, PageDown, Home, End.
 
      6. Составьте программу игры "Пятнашки", выбирая перемещаемую ячейку мышью.
 
      7. Составьте программу, которая по нажатию левой клавиши очищает рабочую область, при движении с нажатой левой клавишей рисует точку в позиции указателя мыши, а при отпускании левой клавиши соединяет все точки в рабочей области друг с другом.

1.4 Программы и их ресурсы

      Многие программы имеют различные заранее подготавливаемые данные, которые в терминах X называются - ресурсами. Это могут быть цвета окон приложения, строки сообщений пользователю и т.д.
      Как правило, программисты создают ресурсы каждый по-своему. В X Window сделана попытка унифицировать этот процесс.

1.4.1 Формат файла ресурсов

      В X файл ресурсов есть обычный текстовый файл, каждая строка которого задает тот или иной параметр (ресурс) программы. (При этом предполагается, что программу "населяют" именованные объекты, связанные в некоторую иерархию). Общий вид строки следующий:
       ‹имя программы›.‹подобъект1›.‹подобъект2›. . .‹подобъектN›.‹имя ресурса›: ‹значение ресурса›
      Подобная строка задает значение ресурса для подобъектов иерархии объектов программы. Например, запись
       myprog.dialogwnd.background: Red
      говорит, что в программе myprog у объекта с именем dialogwnd параметр background (цвет фона) имеет значение Red (красный цвет).
      Вместо имен объектов могут указываться их классы. Обычно класс имеет то же самое имя, что и объект, но начинается с заглавной буквы, например,
       Myprog.dialogwnd.Background: Red
      Часть объектов или классов в левой части строки, задающей ресурс, может заменяться символом '*', например, строка
       myprog*background: Red
      указывает, что для всех объектов программы myprog ресурс background имеет значение Red.
      Связка с помощью символа '.' имеет больший приоритет, чем связка с помощью '*'. Так, если в файле, задающем ресурсы, есть две строки
       myprog*background: Red
       myprog.dialogwnd.background: Green
      то все объекты программы будут иметь ресурс background равный Red, кроме объекта dialogwnd, для которого этот параметр есть Green.

1.4.2 Доступ к ресурсам программ

      Пусть ресурсный файл подготовлен. Как получить доступ к его данным во время работы программы? Для этого X предоставляет набор процедур, которые совокупно называются менеджер ресурсов(Resource Manager), и специальную программу xrdb, которая позволяет считать любой ресурсный файл и включить его в общую таблицу ресурсов сервера. Последняя называется базой данных ресурсов сервера, и представляет собой область памяти, ассоциированную со свойством (property) XA_RESOURCE_MANAGER корневого окна экрана дисплея.

  • Страницы:
    1, 2, 3, 4, 5