Main Page
Статьи Компоненты Ссылки Разное

Полезные советы

Запуск Kylix-приложений отдельно от Kylix

Генерация скриншотов в Kylix-приложении

Низкоуровневый графический вывод

Функция FindWindow для X-Windows

Как не показывать баннер в приложениях, созданных в Kyilx OE?

Как сделать полноэкранное приложение с помощью Borland Kylix ?


Запуск Kylix-приложений отдельно от Kylix

Этот вопрос мне задают так часто, что я решил разместить его здесь.
В: Что делать если мои приложения прекрасно запускаются в среде Kylix, но не запускаются отдельно от нее?
О: Для Kylix 3 все решается очень просто. Kylix 3 включает библиотеку libborqt, которая объединяет в себе функции библиотек libqt и libqtintf. Для того, чтобы запускать Kylix-приложений отдельно от Kylix достаточно разместить эту библиотеку в каталоге /usr/lib/. Даем команды

cp kylix/bin/libborqt-6.9.0-qt2.3.so /usr/lib
ln -s /usr/lib/libborqt-6.9.0-qt2.3.so /usr/lib/libborqt-6.9-qt2.3.so

После этого программы, созданные в Kylix 3, можно запускать отдельно от Kylix.

Решение для Kylix 1

Решений может быть несколько, самое простое выглядит так:
Скопируйте из каталога kylix/bin/ библиотеки libqt и libqtintf в отдельный каталог, например /home/user/libdir/. Создайте файл скрипта (назовите его, например, kapprun) со следующим текстом:

#!/bin/bash
LD_LIBRARY_PATH="/home/user/libdir:$LD_LIBRARY_PATH"
$1

Не забудьте присвоить файлу статус исполнимого:

chmod +x kapprun

Теперь приложения, скомпилированные в Kylix, можно запускать так:

./kapprun ./Project1

Строка ./Project1 передается в качестве аргумента скрипту kapprun.

Вам придется распространиять свои приложения вместе с библиотеками libqt и libqtintf и скриптом, подобным предложенному выше.

Решение для Kylix 2

Если вы хотите распространять графическое приложение отдельно от IDE, вам придется распространять вместе с ним библиотеки libqt.so.2.3.0 и libqtintf-6.5.0-qt2.3.so. Механизм следующий: создаете в каталоге пользователя вашей программы специальный каталог, например kylibs, и копируете туда вышеуказанные библиотеки. Затем в каталоге kylibs командуете:

ln -sf libqtintf-6.5.0-qt2.3.so libqtintf-6.5-qt2.3.so
ln -sf libqt.so.2.3.0 libqt.so.2

Теперь создайте файл k2apprun следующего содержания:

#!/bin/bash
export LD_LIBRARY_PATH=/home/user/kylibs:$LD_LIBRARY_PATH
$*

и присвойте ему статус исполнимого. Приложения запускаются командой:


./k2apprun App

где App - путь к приложению.

Автор: Андрей Боровский


Генерация скриншотов в Kylix-приложении

Выкладываю две процедуры для генерации скриншотов элементов Kylix-приложения и сохранения полученых изображений на диске: GrabControl и GrabForm.

procedure GrabControl(Control : TWidgetControl; const FileName, Format : String);
var
  PM : QPixmapH;
  FN : WideString;
begin
  PM := QPixmap_create;
  QPixmap_grabWidget(PM, Control.Handle, 0, 0, -1, -1);
  FN := FileName;
  QPixmap_save(PM, @FN, PChar(Format));
  QPixmap_destroy(PM);
end;

Первый параметр процедуры - визуальный элемент управ ления скриншот которого нужно получить, потомок класса TWidgetControl. Второй параметр - имя файла, в котором сохраняется изображение. Третий параметр - формат изображения. Следует указывать один из форматов, поддерживаемых Qt-library: PNG, XPM, BMP и т. д.

Если функции GrabControl передать указатель на форму, на полученном скриншоте будет отображена только клиентская часть формы (со всеми дочерними компонентами). Для получения скриншота окна целиком, с заголовком и обрамлением, следует использовать функцию GrabForm:

procedure GrabForm(Form : TCustomForm; const FileName, Format : String);
var
  PM : QPixmapH;
  FN : WideString;
  Root, Parent, Wnd : TWindow;
  Children: PWindow;
  NChildren : Integer;
begin
  if not Form.Visible then Exit;
  PM := QPixmap_create;
  Wnd := QWidget_winID(Form.Handle);
  XQueryTree(QtDisplay, Wnd, @Root, @Parent, @Children, @NChildren);
  XFree(Children);
  while Parent <> Root do
  begin
    Wnd := Parent;
    XQueryTree(QtDisplay, Wnd, @Root, @Parent, @Children, @NChildren);
    XFree(Children);
  end;
  QPixmap_grabWindow(PM, Wnd, 0, 0, -1, -1);
  FN := FileName;
  QPixmap_save(PM, @FN, PChar(Format));
  QPixmap_destroy(PM);
end;

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

Автор: Андрей Боровский


Низкоуровневый графический вывод

Для того, чтобы выполнить графический вывод в окно визуального компонента Kylix средствами X-Windows API, необходимо получить идентификатор окна и связать его с дисплеем. Идентификатор окна для некоторого Kylix компонента Component можно получить при помощи следующей функции из модуля Qt:

WinID := QWidget_winId( QWidgetH(Component.Handle) );

Идентификатор дисплея содержится в переменной QtDisplay, определенной в модуле Qt.

Теперь у нас есть идентификаторы окна и дисплея, которые можно передавать функциям X-Windows API.

Автор: Андрей Боровский


Функция FindWindow для X-Windows

В X-Windows API нет функции, аналогичной функции FindWindow из Win32 API. Выкладываю нерекурсивный вариант функции FindWindow для Kylix.


{ Функция FindWindow  

  © 2001 Андрей Боровский

  Public Domain. }

function FindWindow(Display : PDisplay; 
  Root : TWindow; const Name : String) : TWindow;
const  StackDepth = 32;
type
  TWinArray = array[0..0] of TWindow;
  PWinArray = ^TWinArray;
  StackElem = record
    Children : PWinArray;
    NChildren, Position : Integer;
  end;
var
  Stack : array[0..StackDepth-1] of StackElem;
  StackPtr, i : Integer;
  retName : PChar;
  Wnd : TWindow;
begin
  // Проверяем корневое окно
  XFetchName(Display, Root, @retName); 
  if Name = retName then
  begin
  // Корневое окно подходит
    XFree(retName);
    Result := Root;
    Exit;   
  end;
  Result := 0;
  StackPtr := 0;
  Stack[StackPtr].Position := 0;
  XQueryTree(Display, Root, @Wnd, @Wnd, 
  @(Stack[StackPtr].Children),  @(Stack[StackPtr].NChildren));
  while Result = 0 do  
  if Stack[StackPtr].Position < Stack[StackPtr].NChildren then  
  begin
    Wnd := Stack[StackPtr].Children^[Stack[StackPtr].Position];
    XFetchName(Display, Wnd, @retName);
    if Name = retName then
    begin
  // Окно найдено
      Result := Wnd;
      XFree(retName);
      for i := 0 to StackPtr do XFree(Stack[i].Children);
    end else
    begin
      XFree(retName);
      if StackPtr < StackDepth - 1 then
      begin
        Inc(StackPtr);
        XQueryTree(Display, Wnd, @Wnd, @Wnd,
          @(Stack[StackPtr].Children),  @(Stack[StackPtr].NChildren));
        Stack[StackPtr].Position := 0;
      end else Inc(Stack[StackPtr].Position);
    end;
  end else
  begin
    XFree(Stack[StackPtr].Children);
    Dec(StackPtr);
    if StackPtr = -1 then Exit;    // Окно не найдено
    Inc(Stack[StackPtr].Position);
  end;
end;

Функция позволяет получить идентификатор окна по его названию. В параметре Display передается указатель на X-дисплей, параметр Root должен содержать идентификатор окна, с которого следует начать поиск (обычно это корневое окно дисплея). В параметре Name передается имя окна, идентификатор которого требуется получить. Константа StackDepth ограничивает максимальную "глубину погружения" при обходе дерева окон.

Для того, чтобы получить идентификатор окна с именем SomeWndName, вызваем FindWindow следующим образом:

WinID := FindWindow(QtDisplay, QWidget_winID(Application.Desktop), 'SomeWndName');

Автор: Андрей Боровский


Как не показывать баннер в приложениях, созданных в Kyilx OE?

Приложения, созданные в Kylix OE, выводят при запуске небольшое окошко, в котором предупреждают о том, что "данное приложение создано в некоммерческой версии Kylix ...". Для того, чтобы приложение при запуске не показывало это окно, его необходимо запускать с ключом -ns.

Автор: Андрей Боровский


Как сделать полноэкранное приложение с помощью Borland Kylix?

Иногда необходимо, чтобы клиентская область формы Kylix-приложения занимала все пространство экрана. Это может понадобиться например в играх и приложениях multimedia. Перевести форму приложения в полноэкранный режим можно с помощью вызова:

QWidget_showFullScreen(Form.Handle);

а вернуть в нормальный режим - с помощью вызова

QWidget_showNormal(Form.Handle);

Следует помнить, что в полноэкранном режиме переключение на другие приложения (с помощью [Alt]-[Tab]) заблокировано.

Автор: Андрей Боровский