1

Тема: Visual Kolibri Library (VKL)

Мой проект Delphi для KolibriOS подразумевает разработку объектно-ориентированных библиотек. Одной из таких библиотек может стать Visual Kolibri Library (VKL). Не полный аналог VCL, конечно, но минимальную абстракцию визуальных компонентов должна обеспечить. Из-за нехватки времени, скорее всего, никогда не будет написана. Но если кто-то хочет взяться — готов курировать.

Добавлено 20.05.2020 в 19:08

В теме на форуме KolibriOS пишут документацию по кишкам box_lib.obj. Хорошее место для начала разработки VKL.

2

Re: Visual Kolibri Library (VKL)

Freeman пишет:

пишут документацию по кишкам box_lib.obj. Хорошее место для начала разработки VKL.

:-) ну я бы не сказал
Я это заметил, конечно, ещё раньше.
board.kolibrios.org/viewtopic.php?f=4&t=4210#p74461

ProMiNick пишет:

shift_old - какая то ахинея для внутренних нужд (выделение издавна это диапазон символов между позицией каретки и позицией выделения, но тут зачем то еще это незнамо-что.

Ну такая себе документация :-)

А вообще, так уж совпало, что именно EditBox — наиболее востребованный компонент, который имеет "такие" внутренности

ProMiNick пишет:

чтобы у тех, кто будет читать и разбираться во внутренностях исходников box_lib в голове не образовалось каши (а вернее с точностью до наоборот) доблестные разработчики box_lib обозначили поля вышеописанной структуры через приставку "ed_", а флаги тоже обозначили в малом регистре - так чтобы они выглядели как близнецы братья и сам черт сломал ногу.

Хотя вот я делал компонент ProgressBar и дорабатывал Frame и надеюсь, что получилось более понятно websvn.kolibrios.org/filedetails.php?re … 9#line-482

Сравните теперь с EditBox

shift_color           equ [edi + 16] ; select color
ed_focus_border_color equ [edi + 20] ; border color active
ed_blur_border_color  equ [edi + 24] ; border color inactive

ну вот и почему бы сразу не написать вот так

select_color      equ [edi + 16] ;
ed_border_color_active   equ [edi + 20] ;
ed_border_color_inactive equ [edi + 24] ;

3

Re: Visual Kolibri Library (VKL)

select_color      equ [edi + 16] ;
ed_border_color_active   equ [edi + 20] ;
ed_border_color_inactive equ [edi + 24] ;

Нет ничего сложного чтобы заменить названия на логичные. Sublime и Notepad++ точно умеют массовое переименование.

Я кстати сам вносил исправления EditBox не так давно smile

ProMiNick хочет переписать BoxLib под свои нужды, при этом поломав совместимость.

4 (изменено: Freeman, 01.06.2020 в 22:28)

Re: Visual Kolibri Library (VKL)

Модератор: обсуждение использования Delphi SDK for KolibriOS 2020-05 отделено.

5

Re: Visual Kolibri Library (VKL)

Раз уж портирования VCL не будет.
То, получается, что это будет свой какой-то велосипед.
VCL могло бы дать возможность перенести уже существующие проекты.
Раз это не планируется, то можно сделать, чтобы хотя бы переносить готовый код можно было в рамках этого "нового велосипеда".

Я имею в виду такой пример http://kolibriosandfasm.mybb.ru/viewtopic.php?id=24
Можно разрабытывать GUI-проект под виндой, а потом просто перекомпилировать его под KolibriOS.
Насколько реальна такая идея?

Есть примитивный пример ListBox-а, но без скроллбара.
Реализован по аналогии с компонентами box_lib.
То есть, при вызове функций просто передаётся указатель на структуру ListBox-a.
Всё что нужно — передать указатель на список с данными.
При желании можно сделать этот ListBox одновременно и под винду, и под Колибри.

А вообще наиболее востребованные имхо компоненты — это EditBox, ScrollBar и ListBox.

Тогда, как пожелание, этот велосипед должен быть гибким, то есть, например, все действия должны выполняться не только мышью(ну кроме ввода символов), но и клавиатурой.
Полное управление с помощью клавиатуры скроллбаром, листбоксом.
Перемещение фокуса между контролами(например, TAB и Ctrl+TAB).
Должно быть удобно, в box_lib такого нет — придётся городить доп. обвязку.
А лучше тогда вообще городить полностью всё.

6

Re: Visual Kolibri Library (VKL)

В настоящий момент мне кажется, что в реализации оконной библиотеки нужно ориентироваться не на VCL, а на браузер. То есть, сделать так, будто контролы создаются браузером, имеется CSS, и пр.

7 (изменено: Freeman, 10.01.2021 в 04:34)

Re: Visual Kolibri Library (VKL)

Существуют различные способы позиционирования элементов управления в окне приложения.
Можно привести в качестве примера менеджеров расположения из Python Tkinter:

  • pack — самый простой, автоматически размещает виджеты в окне

  • place — абсолютное позиционирование

  • grid — размещает виджеты по сетке

https://www.python-course.eu/tkinter_la … gement.php
https://www.programminginpython.com/lay … rid-place/

Но чем "умнее" менеджер расположения, тем сложнее его реализовать, соответственно и кода будет больше.
Однако более "умный" менеджер расположения позволяет размещать элементы более гибко.

Я вообще как-то начинал делать более нормальную, по сравнению с box_lib, GUI-библиотеку.
Но, к сожалению, так и не доделал.
Она была написана на ассемблере NASM.

Возможно, я кое-что попытаюсь переписать на Delphi в хоть каком-то объектно-ориентированном стиле.
Суть, в общем, в том, что элементы рисуются в оконный буфер, а затем при полной перерисовке этот буфер выводится одним системным вызовом в окно.
Элементы могут иметь фокус.
Обрабатываются сообщения от мыши и клавиатуры.
Нажатие клавиатуры отправляются активному элементу.
При нажатии мышью в окне с помощью функции InRect определяется, в какой элемент попал указатель мыши, затем этот элемент получает фокус.
И т.д и т.п.
Шрифт используется из файла формата pnm(поддерживается в KolibriOS)
Но можно и системный использовать.
Просто когда я это начинал делать, то в KolibriOS не было масштабирования для системных шрифтов, и шрифты были — один моноширинный и второй различной ширины, короче, давно это уже было smile

Выглядит это вот так(CheckBox, OptionBox, Button, Frame и Panel(но это по сути тоже Button, только Disabled)):
misc.php?action=pun_attachment&item=83&download=0
такое приложение весит примерно 5 килобайтов.

Post's attachments

test.gif, 41.02 Кб, 304 x 218
test.gif 41.02 Кб, 77 скачиваний с 2021-01-10 

8

Re: Visual Kolibri Library (VKL)

0CodErr пишет:

Но чем "умнее" менеджер расположения, тем сложнее его реализовать, соответственно и кода будет больше.
Однако более "умный" менеджер расположения позволяет размещать элементы более гибко.

Его можно сделать необязательным. Раз уж VCL копировать не планируем, надо делать по-правильному, по-русски.

0CodErr пишет:

Возможно, я кое-что попытаюсь переписать на Delphi в хоть каком-то объектно-ориентированном стиле.

Попробуй. Учитывай, что ООП у нас будет на object-ах. Скоро их добавлю.

0CodErr пишет:

Просто когда я это начинал делать, то в KolibriOS не было масштабирования для системных шрифтов, и шрифты были — один моноширинный и второй различной ширины, короче, давно это уже было smile

Системный шрифт Колибри теперь поддерживает Unicode. Это надо учитывать. После реализации строк добавлю Unicode-пример. Уже есть идея и заготовка. Для браузера Unicode обязателен.

Наверное, и отрисовку шрифтов надо сделать через ООП, заменяемой. Сейчас уже есть же какие-то RasterWorks, FreeType... TrueType где-то поддерживается?

9

Re: Visual Kolibri Library (VKL)

Freeman пишет:

Системный шрифт Колибри теперь поддерживает Unicode. Это надо учитывать.

Проблема в том, что для вывода системного шрифта нужен системный вызов, а это тормозно.
Такой шрифт должен быть не в ядре, а в системной библиотеке.

Предположим, на твоём экране умещается 50 строк текста.
Для вывода его на экран потребуется 50 системных вызовов.
Если бы использовался не ядерный шрифт, то можно было бы сперва вывести всё в буфер, и после этого ОДНИМ системным вызовом вывести на экран.

Ну FreeType ещё лучше было бы, но это нужна библиотека.
Не припомню, чтобы такая была среди стандартных библиотек.
Она входит в iso-образ, но в формате PE.
C помощью сис. функции её не загрузишь.
Как я понял, это всё ради сишных программ сделано было.
Они PE грузят, только всё это получается через "одно место"

Добавлено 2021-01-10 в 15:11

Freeman пишет:

Уже есть идея и заготовка. Для браузера Unicode обязателен.

Планируется создание браузера?
Может тогда стоит тему создать, кто-то мог бы высказать пожелания и предложения по разработке, дизайну, функционалу, и т.д.

Добавлено 2021-02-11 в 22:05

Выкладываю пример, переписанный с NASM на Pascal.
Пример поддерживает системные цвета, вот так это выглядит при смене системных цветов(например в приложении Appearance):
misc.php?action=pun_attachment&item=85&download=0
 
Создаётся окно со стартовыми координатами относительно центра экрана.
  Далее создаются несколько элементов управления(некоторые из них(Button3 и Button5) невидимые Visible = False, поэтому они не отображаются)
  Назначаются обработчики событий щелчка мыши для кнопок(
  Button1Click, Button2Click, Button4Click, в них происходит проверка Check1.Value и Option2.Value.
При нажатии мышью или клавишей "пробел" на кнопки изменяется текст заголовка окна)
  После этого начинается выполнение - Run

  Процедура SetApplicationDirectoryAsCurrent
  устанавливает директорию, из которой запущено это приложение
  в качестве текущей директории, это сделано для удобства работы
  с файловыми путями (в данный момент пир загрузке шрифтов)
  Может быть, эта процедура и не так сильно нужна, так как
  шрифты можно копировать при установке приложения в
  директорию "/sys/fonts" и грузить всегда строго оттуда
  Но конкретно в данном примере файлы шрифтов *.ppm должны
  находится в одной папке с приложением,
  однако пути к шрифтам(FontName1, FontName2) можно менять на свои.

  Не так просто превратить ассемблерный код в Pascal
  поэтому многие вещи даже просто были переписаны заново
  об оптимизации тут речи не идёт, начинать с этого было бы странно

  Что касается шрифтов, то можно запросто заменить на тот
  формат, который нравится, имею в виду, что можно будет использовать
  как системный, так и freetype — просто ещё не реализовано

  Переключатели Option могут быть сгруппированы по различным группам.
  Для того, чтобы различать эти группы, служит поле GroupId у элемента управления Option
  У обоих Option в данном примере GroupId = 0, поэтому они относятся к одной группе

  Со включенной опцией DEBUG в консоль будет выводиться некоторая информация.
  Это может быть полезно при отладке.

Процедура SetApplicationDirectoryAsCurrent — возможно лишняя, но в данный момент она находится в коде самого примера, в будущем можно будет при необходимости найти для неё более подходящее место.

Код приложения выглядит вот так:

program GUI2DExample;

uses
  KolibriOS, GUI2D;

const
// fonts that we use
  FontName1 = './6x13.ppm';
  FontName2 = './courier.ppm';

var
// declare our controls
  Button1, Button2, Button3,
  Button4, Button5: TButton;
  Panel1, Panel2: TPanel;
  Check1, Check2: TCheck;
  Option1, Option2: TOption;

// below are some event handlers for our Buttons

procedure Button1Click;
begin
  if Check1.Value then
    SetWindowCaption('Button1Click, Check1 is Checked')
  else
    SetWindowCaption('Button1Click');
end;

procedure Button2Click;
begin
  SetWindowCaption('Button2Click');
end;

procedure Button4Click;
begin
  if Option2.Value then
    SetWindowCaption('Button4Click, Option2 is Selected')
  else
    SetWindowCaption('Button4Click');
end;

// dont sure where this should be placed
// note that if app launched from the file manager
// than this may be unnecessary
procedure SetApplicationDirectoryAsCurrent;
const
  AppPath: PPAnsiChar = PPAnsiChar(32);
var
  i: LongWord;
begin
  i := 0;
  while AppPath^[i] <> #0 do Inc(i);
  while AppPath^[i] <> '/' do Dec(i);
  AppPath^[i] := #0;
  SetCurrentDirectory(AppPath^);
  AppPath^[i] := '/'; // restore original AppPath
end;

begin
  SetApplicationDirectoryAsCurrent;

// Create Window centered relative to the screen
  Window.Create(supCenterScreen, 299, 214, 'GUI2D Example');

// Create Controls
  Button1.Create(8, 144, 84, 36, 'Button1', CONTROL_BACKSTYLE_GRADIENT, FontName2, True, True);
  Button2.Create(104, 144, 84, 36, 'Button2', CONTROL_BACKSTYLE_GRADIENT, FontName2, True, True);
  Button3.Create(48, 144, 76, 28, 'Button3', CONTROL_BACKSTYLE_GRADIENT, nil, False, True);
  Button4.Create(200, 144, 84, 36, 'Button4',CONTROL_BACKSTYLE_GRADIENT, FontName2, True, True);
  Button5.Create(10, 130, 76, 27, 'Button5', 0, nil, False, True);
  Panel1.Create(8, 8, 273, 113, 0, CONTROL_BORDERSTYLE_RIDGED, True, True);
  Panel2.Create(8, 130, 273, 5, 0, CONTROL_BORDERSTYLE_RAISED, True, True);
  Check1.Create(16, 24, 76, 19, 'Check1', CONTROL_BACKSTYLE_GRADIENT, 0, FontName1, True, True, True);
  Check2.Create(16, 48, 76, 19, 'Check2', CONTROL_BACKSTYLE_GRADIENT, 0, FontName1, True, True, False);
  Option1.Create(192, 24, 76, 19, 'Option1', CONTROL_BACKSTYLE_GRADIENT, 0, FontName1, True, True, False);
  Option2.Create(192, 48, 76, 19, 'Option2', CONTROL_BACKSTYLE_GRADIENT, 0, FontName1, True, True, True);

// Set event handlers for Clicks on the Buttons
  Button1.OnClick := Button1Click;
  Button2.OnClick := Button2Click;
  Button4.OnClick := Button4Click;

// And than 'Run'
  Run;
end.

  Выкладываю архив "GUI2D_Test.7z", в котором также
  содержится уже скомпилированное и сжатое приложение "GUI2D_Test.kex"
  Для компиляции как обычно используется SDK 
  Скачайте SDK, распакуйте архив "GUI2D_Test" в папку "My" внутри SDK
  и используйте build.bat для сборки, в папке "Bin" должно появиться скомпилированное приложение а также скопированные файлы шрифтов *.ppm

Добавлено 2023-03-12 в 16:23

Переделал в более похожем на ООП стиле.
Теперь используются конструкторы и абстрактные виртуальные методы.
Заменил все ассемблерные версии функций на Pascal-версии, чтобы код был более понятным.
Для работы модуля необходимо в System иметь _objsetup, _objcopy, _AbstractError, _RunError, я скопировал их как есть.

Особенности и нюансы

Колесико мыши работает не только в листбоксе, но и для каждого отдельного скроллбара.
Для группировки элементов Option используется параметр GroupId — целочисленный идентификатор группы.
В текстовом поле не поддерживается copy\paste и выделение текста.
Скроллбар не поддерживает отрицательные значения, это было бы не логично, так как при скроллинге значения позиции принимают значения от нуля и выше.
Однако если необходимо изменять отрицательные значения, то можно использовать элемент управления Track, он это поддерживает.
Обычно курсор в текстовом поле представляет собой либо вертикальную черту между символами, либо горизонталную под символом, но я решил их совместить: 2 черты горизонтальная и вертикальная одновременно.
В листбоксе область видимости может содержать только целое число выводимых элементов, если элемент не помещаются полностью в области видимости, то он не выводится, обрезанные элементы не допускаются, поэтому высоту листбокса следует выбирать кратным высоте элемента, чтобы не оставалось пустого пространства внизу.

Про используемые в данный момент шрифты

Путь к шрифту удобнее указывать относительный.
По умолчанию текущий путь приложения в KolibriOS — это путь к рамдиску, либо путь наследуется от вызывающего приложения.
Если программа запущена из файлового менеджера или из Shell, то текущий путь будет равен пути к приложению, в других случаях это не гарантируется.
В примерах используется SetApplicationDirectoryAsCurrent для установки пути к приложению в качестве текущего пути.
Если текст не отображается — вероятно, не верно указан путь к шрифту. 
Файлы шрифтов в идеале должны находится в папке Fonts, копироваться туда при установке программы тогда путь будет всегда один и тот же, ещё их можно сжать и в сжатом виде размер файла будет гораздо меньше.
По нескольким тестам оказалось, что сжатие изображения KPACK было лучше, чем сжатие PNG.
Шрифт хранится в файле формата PNM(P6) — 24 битные(rgb, rgb, ...) с расширением ".ppm"
Конечно, использовать 3 байта на каждый пикслеь шрифта — чересчур расточительно, но для тестирования функции вывода текста вполне подходит.

Вопросы реализации

Остаются некоторые вопросы реализации: нужно ли для каждого текстового элемента управления создавать свой внутренний буфер для текста или же достаточно задокументировать, что передаём указатель на текст и больше текст не трогаем, сейчас только Edit имеет внутренний буфер, так как логично, что вызывающая сторона понятия не имеет, как с этим буфером нужно обращаться, однако для Label и Button вполне хватает указателей на текст для Caption.

В процессе взаимодействия с элементами управления не происходит увеличения потребления памяти, так как дополнительная память просто не используется.

Теперь пояснение, как можно автоматически сгенерировать код для элементов управления на форме в самой IDE, чтобы не приходилось писать координаты и размеры каждый раз вручную:

Последовательность действий

Как обычно запустите IDE, создайте новый проект "Application".
Накидайте на форму нужные элементы управления из поддерживаемых(см. ниже).
Добавьте в модуль с формой приведённый ниже код.
В обработчике FormCreate добавьте вызов GenCode вот так:

procedure TForm1.FormCreate(Sender: TObject);
begin
  GenCode(Self);
end;

Скомпилируйте и запустите проект.
В буфере обмена будет сгенерированный код(нажмите Ctrl+V чтобы его вставить).
Код почти готов, нужно немного отредактировать его: написать нужные обработчики событий, путь к шрифтам и учесть случай, когда ListBox или TabStrip не имеют строк/табов.
Следует учитывать, что элементы всё же отличаются от стандартных VCL, например, TabStrip — просто полоса вкладок без панели(которая есть у TabControl из VCL).

Код, который необходимо добавить в модуль с формой
(*                           -*- ClipBrdCodeGen -*-
  Supported controls: Button, Label, StaticText, ScrollBar, CheckBox, RadioButton,
    Edit, ListBox, TrackBar, TabControl, Panel.
  Note: appearance of some GUI2D controls may differ from the standard VCL.
  Place the controls you need in the form and launch the application,
  after that the clipboard will contain the generated code.
  Use the "Ctrl+V" keys or the right mouse button "Menu -> Paste".

  Some fixes in the generated code are needed:
    1. define real path of FontName, for example relative:
      const Font_Courier = './courier.ppm';
    2. resolve case of zero count Items|Tabs of ListBox|TabStrip
    3. write and assign event handlers for control events:
        Button.OnClick, Track.OnChange, ScrollBar.OnScroll, TabStrip.OnChange
*)

uses
  ClipBrd
{$IF NOT Declared(ComCtrls)}
, ComCtrls
{$IFEND}
{$IF NOT Declared(StdCtrls)}
, StdCtrls
{$IFEND}
{$IF NOT Declared(ExtCtrls)}
, ExtCtrls
{$IFEND}
;

procedure GenCode(Form: TForm);
var
  ResultString, Strings: AnsiString;
  ControlIndex, i: Integer;
  K: TControl;

  // replace [' ', '-', '@'...] in the font name by underscores
  function GetFontName(fn: AnsiString): AnsiString;
  var
    i: Integer;
  begin
    for i := 1 to Length(fn) do
      if fn[i] in [' ', '-', '@', '/', '\', '!', '#', '$', '%', '^',
        '&', '*', '-', '+', '=', '?', ';', ':', '~', '(', ')'] then
        fn[i] := '_';
    Result := 'Font_' + fn;
  end;

  // show error for unknown controls
  procedure Unknown(Name: AnsiString);
  begin
    ShowMessage('Unsupported control "' + Name + '"');
    Halt;
  end;

  // add code to result
  procedure Out(Code: AnsiString);
  begin
    ResultString := ResultString + Code;
  end;

begin
  with Form do
  begin
    Out('program GUI2DProject;'#13#10#13#10 +
      'uses'#13#10'  GUI2D;'#13#10#13#10);

    // generate constant array of Items|Tabs of ListBox|TabStrip
    Out('const'#13#10);
    for ControlIndex := 0 to ControlCount - 1 do
    begin
      K := Controls[ControlIndex];
      if K.ClassNameIs('TListBox') then
        with TListBox(K) do
        begin
          Strings := '';
          for i := 0 to Count - 2 do
            Strings := Strings + #39 + Items[i] + #39 + ', ';
          if Count <> 0 then
            Strings := Strings + #39 + Items[Count - 1] + #39;
          Out('  ' + Name + 'Items: array[0..'
           + IntToStr(Count - 1) + '] of PAnsiChar =' + #13#10
           + '    (' + Strings + ');' + #13#10#13#10);
        end
      else if K.ClassNameIs('TTabControl') then
      begin
        with TTabControl(K) do
        begin
          Strings := '';
          for i := 0 to Tabs.Count - 2 do
            Strings := Strings + #39 + Tabs[i] + #39 + ', ';
          if Tabs.Count <> 0 then
            Strings := Strings + #39 + Tabs[Tabs.Count - 1] + #39;
          Out('  ' + Name + 'Tabs: array[0..'
           + IntToStr(Tabs.Count - 1) + '] of PAnsiChar =' + #13#10
           + '    (' + Strings + ');' + #13#10#13#10);
        end
      end;
    end;

    // declare controls variables
    Out('var'#13#10);
    for ControlIndex := 0 to ControlCount - 1 do
      with Controls[ControlIndex] do
        if ClassNameIs('TButton') then
          Out('  ' + Name + ': TButton;'#13#10)
        else if ClassNameIs('TLabel') or ClassNameIs('TStaticText') then
          Out('  ' + Name +  ': TLabel;'#13#10)
        else if ClassNameIs('TScrollBar') then
          Out('  ' + Name +  ': TScrollBar;'#13#10)
        else if ClassNameIs('TCheckBox') then
          Out('  ' + Name +  ': TCheck;'#13#10)
        else if ClassNameIs('TRadioButton') then
          Out('  ' + Name +  ': TOption;'#13#10)
        else if ClassNameIs('TEdit') then
          Out('  ' + Name +  ': TEdit;'#13#10)
        else if ClassNameIs('TListBox') then
          Out('  ' + Name +  ': TTextListBox;'#13#10)
        else if ClassNameIs('TTrackBar') then
          Out('  ' + Name +  ': TTrack;'#13#10)
        else if ClassNameIs('TTabControl') then
          Out('  ' + Name +  ': TTabStrip;'#13#10)
        else if ClassNameIs('TPanel') then
          Out('  ' + Name +  ': TPanel;'#13#10)
        else
          Unknown(Name);

    // generate event handlers for control events(implement it by yourself)
    Out(#13#10);
    for ControlIndex := 0 to ControlCount - 1 do
      with Controls[ControlIndex] do
        if ClassNameIs('TButton') then
          Out('procedure ' + Name + 'Click;'#13#10'begin'#13#10#13#10'end;'#13#10#13#10)
        else if ClassNameIs('TScrollBar') then
          Out('procedure ' + Name + 'Scroll;'#13#10'begin'#13#10#13#10'end;'#13#10#13#10)
        else if ClassNameIs('TTrackBar') then
          Out('procedure ' + Name + 'Change;'#13#10'begin'#13#10#13#10'end;'#13#10#13#10)
        else if ClassNameIs('TTabControl') then
          Out('procedure ' + Name + 'Change;'#13#10'begin'#13#10#13#10'end;'#13#10#13#10);

    // generate a call to control constructors
    Out('begin'#13#10 + '// create controls'#13#10);
    for ControlIndex := 0 to ControlCount - 1 do
    begin
      K := Controls[ControlIndex];
      if K.ClassNameIs('TButton') then
        with TButton(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + #39 + Caption + #39 + ', cbksGradient' + ', ' + GetFontName(Font.Name) + ');'#13#10)
      else if K.ClassNameIs('TLabel') then
        with TLabel(K) do
        begin
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + #39 + Caption + #39 + ', cbksNormal' + ', cbsNone, ' + GetFontName(Font.Name));
          case Alignment of
            taLeftJustify:  Out(');'#13#10); // Default value can be omitted
            taRightJustify: Out(', taRightJustify);'#13#10);
            taCenter:       Out(', taCenter);'#13#10);
          end;
        end
      else if K.ClassNameIs('TStaticText')then
        with TStaticText(K) do
        begin
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + #39 + Caption + #39 + ', cbksNormal' + ', cbsNone, ' + GetFontName(Font.Name));
          case Alignment of
            taLeftJustify:  Out(');'#13#10); // Default value can be omitted
            taRightJustify: Out(', taRightJustify);'#13#10);
            taCenter:       Out(', taCenter);'#13#10);
          end;
        end
      else if K.ClassNameIs('TScrollBar') then
        with TScrollBar(K) do
        begin
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + IntToStr(Min) + ', ' + IntToStr(Max) + ', ' + IntToStr(Position));
          case Kind of
            sbVertical:   Out(', sbVertical);'#13#10);
            sbHorizontal: Out(', sbHorizontal);'#13#10);
          end;
        end
      else if K.ClassNameIs('TCheckBox') then
        with TCheckBox(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + #39 + Caption + #39 + ', cbksGradient' + ', cbsNone, ' + GetFontName(Font.Name) + ', ' + BoolToStr(Boolean(State), True) + ');'#13#10)
      else if K.ClassNameIs('TRadioButton') then
        with TRadioButton(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + #39 + Caption + #39 + ', cbksGradient' + ', cbsNone, ' + GetFontName(Font.Name) + ', ' + BoolToStr(Checked, True) + ');'#13#10)
      else if K.ClassNameIs('TEdit') then
        with TEdit(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + #39 + Text + #39 + ', ' + GetFontName(Font.Name) + ');'#13#10)
      else if K.ClassNameIs('TListBox') then
        with TListBox(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', @' + Name + 'Items[0], Length(' + Name + 'Items)' + ', ' + GetFontName(Font.Name) + ');'#13#10)
      else if K.ClassNameIs('TTrackBar') then
        with TTrackBar(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', ' + IntToStr(Min) + ', ' + IntToStr(Max) + ', ' + IntToStr(Position) + ');'#13#10)
      else if K.ClassNameIs('TTabControl') then
        with TTabControl(K) do
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height)
            + ', @' + Name + 'Tabs[0], Length(' + Name + 'Tabs)' + ', ' + GetFontName(Font.Name) + ');'#13#10)
      else if K.ClassNameIs('TPanel') then
        with TPanel(K) do
        begin
          Out('  ' + Name + '.Create(' + IntToStr(Left) + ', ' + IntToStr(Top) + ', ' + IntToStr(Width) + ', ' + IntToStr(Height) + ', cbksNormal');
          case BevelInner of
            bvNone:
              case BevelOuter of
                bvNone: Out(', cbsNone);'#13#10);
                bvLowered: Out(', cbsSunken);'#13#10);
                bvRaised, bvSpace: Out(', cbsRaised);'#13#10);
              end;
            bvLowered:
              case BevelOuter of
                bvNone, bvLowered: Out(', cbsSunken);'#13#10);
                bvRaised, bvSpace: Out(', cbsRidged);'#13#10);
              end;
            bvRaised, bvSpace:
              case BevelOuter of
                bvNone, bvRaised,
                  bvSpace: Out(', cbsRaised);'#13#10);
                bvLowered: Out(', cbsEtched);'#13#10);
              end;
          end;
        end
      else
        Unknown(Name);
    end;

    // generate set event handlers for control events
    // need to implement these procedures by yourself
    ResultString := ResultString + #13#10'// set event handlers'#13#10;
    for ControlIndex := 0 to ControlCount - 1 do
      with Controls[ControlIndex] do
        if ClassNameIs('TButton') then
          Out('  ' + Name + '.OnClick := ' + Name + 'Click;'#13#10)
        else if ClassNameIs('TScrollBar') then
          Out('  ' + Name + '.OnScroll := ' + Name + 'Scroll;'#13#10)
        else if ClassNameIs('TTrackBar') then
          Out('  ' + Name + '.OnChange := ' + Name + 'Change;'#13#10)
        else if ClassNameIs('TTabControl') then
          Out('  ' + Name + '.OnChange := ' + Name + 'Change;'#13#10);

    // creating autosized Window and Run application
    Out(#13#10'// create Window'#13#10 +
      '  Window.Create(supCenterScreen, asoFitToControls, ' + #39 + 'GUI2D Example' + #39 + ');'#13#10#13#10);
    Out('  Run;'#13#10'end.');

    // now put the generated code to the clipboard
    Clipboard.AsText := ResultString;
  end;
end;

   
Некоторые примеры, использующие сгенерированный таким образом код(для сравнения на скриншотах также показано исходное окно с контролами):
misc.php?action=pun_attachment&amp;item=171&amp;download=0

Код примера
program GUI2DProject;

uses
  KolibriOS, GUI2D;

const
  List1Items: array[0..11] of PAnsiChar =
    ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');

  Font_Anka_Coder = './Anka.ppm';        
    
var
  Panel1: TPanel;
  Button1: TButton;
  List1: TTextListBox;
  Track1: TTrack;
  Check1: TCheck;
  Option1: TOption;
  Check2: TCheck;
  Option2: TOption;
  Button2: TButton;
  Panel2: TPanel;
  Button3: TButton;
  Label1: TLabel;
  Label2: TLabel;

  
  S: array [0..10] of AnsiChar;

procedure IntToStr(Number: Integer; Str: PAnsiChar);
var
  Digit, Weight: Integer;
begin
  if Number <> 0 then
  begin
    if Number < 0 then
    begin
      Number := -Number;
      Str^ := '-';
      Inc(Str);    
    end;
    Weight := 1000000000; //  10^9 <= High(Integer) <= 10^10
    while Number < Weight do
      Weight := Weight div 10;
    while Weight > 0 do
    begin
      Digit := Number div Weight;
      Dec(Number, Weight * Digit);
      Weight := Weight div 10;
      Str^ := AnsiChar(Integer('0') + Digit);
      Inc(Str);
    end;
  end
  else
  begin
    Str^ := '0';
    Inc(Str);
  end;
  Str^ := #0;
end;    
  
procedure Button1Click;
begin
  Label2.Caption := List1.Text;
end;

procedure Track1Change;
begin
  IntToStr(Track1.Value, S);
  Label1.Caption := S;
end;

procedure Button2Click;
begin

end;

procedure Button3Click;
begin

end;

// dont sure where this should be placed
// note that if app launched from the file manager
// than this may be unnecessary
procedure SetApplicationDirectoryAsCurrent;
const
  AppPath: PPAnsiChar = PPAnsiChar(32);
var
  i: LongWord;
begin
  i := 0;
  while AppPath^[i] <> #0 do Inc(i);
  while AppPath^[i] <> '/' do Dec(i);
  AppPath^[i] := #0;
  SetCurrentDirectory(AppPath^);
  AppPath^[i] := '/'; // restore original AppPath
end;

begin
  SetApplicationDirectoryAsCurrent;

// create controls
  Panel1.Create(6, 8, 355, 137, cbksNormal, cbsRidged);
  Button1.Create(145, 50, 79, 23, 'Select->', cbksGradient, Font_Anka_Coder);
  List1.Create(19, 22, 121, 106, @List1Items[0], Length(List1Items), Font_Anka_Coder);
  Track1.Create(152, 79, 145, 20, 11, 33, 20);
  Check1.Create(177, 24, 81, 17, 'Check1', cbksGradient, cbsNone, Font_Anka_Coder, True);
  Option1.Create(265, 112, 81, 17, 'Option2', cbksGradient, cbsNone, Font_Anka_Coder, True);
  Check2.Create(265, 24, 81, 17, 'Check2', cbksGradient, cbsNone, Font_Anka_Coder, False);
  Option2.Create(177, 112, 81, 17, 'Option1', cbksGradient, cbsNone, Font_Anka_Coder, False);
  Button2.Create(48, 168, 105, 25, 'Button2', cbksGradient, Font_Anka_Coder);
  Panel2.Create(8, 153, 353, 5, cbksNormal, cbsRaised);
  Button3.Create(216, 168, 105, 25, 'Button3', cbksGradient, Font_Anka_Coder);
  Label1.Create(304, 82, 45, 15, 'Value', cbksNormal, cbsNone, Font_Anka_Coder, taCenter);
  Label2.Create(231, 53, 122, 15, 'Selected', cbksNormal, cbsNone, Font_Anka_Coder, taCenter);

// set event handlers
  Button1.OnClick := Button1Click;
  Track1.OnChange := Track1Change;
  Button2.OnClick := Button2Click;
  Button3.OnClick := Button3Click;

// create Window
  Window.Create(supCenterScreen, asoFitToControls, 'GUI2D Example');

  Run;
end.


misc.php?action=pun_attachment&amp;item=172&amp;download=0

Код примера
program GUI2DExample;

uses
  KolibriOS, GUI2D;

const
// fonts that we use
  Font_PragmataPro = './Pragmata.ppm';
  Font_SCPro = './SCPro.ppm';
  Font_Anka = './Anka.ppm';
  Font_Cozette = './Cozette.ppm';
  Font_AnonPro = './AnonPro.ppm';
  Font_JBMono = './JBMono.ppm';


  ListItemsNumbers: array[0..9] of PAnsiChar =
    ('One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten');

  ListItemsDays: array[0..6] of PAnsiChar =
    ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');

  ListItemsCountrys: array [0..29] of PChar =
  ( 'Norway',
    'Switzerland',
    'Ireland',
    'Germany',
    'Hong Kong',
    'Australia',
    'Iceland',
    'Sweden',
    'Singapore',
    'Netherlands',
    'Denmark',
    'Finland',
    'Canada',
    'New Zealand',
    'United Kingdom',
    'United States',
    'Belgium',
    'Liechtenstein',
    'Japan',
    'Austria',
    'Luxembourg',
    'Israel',
    'South Korea',
    'Slovenia',
    'Spain',
    'Czech Republic',
    'France',
    'Malta',
    'Italy',
    'Estonia');


  TabStrip1Tabs: array[0..2] of PAnsiChar =
    ('Days', 'Countries', 'Numbers');

var
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Label4: TLabel;
  Label5: TLabel;
  Label6: TLabel;
  Shape2: TPanel;
  Label7: TLabel;
  Label8: TLabel;
  Label9: TLabel;
  Picture1: TPanel;
  Slider2: TTrack;
  TabStrip1: TTabStrip;
  List1: TTextListBox;
  HScroll1: TScrollBar;
  VScroll1: TScrollBar;
  Slider1: TTrack;
  Command1: TButton;
  Command2: TButton;
  Command3: TButton;
  Text1: TEdit;
  Command4: TButton;
  Command5: TButton;
  Command6: TButton;
  Check2: TCheck;
  Check1: TCheck;
  Option3: TOption;
  Option2: TOption;
  Option1: TOption;

  Label1Caption: array [0..10] of AnsiChar;
  Label2Caption: array [0..10] of AnsiChar;
  Label3Caption: array [0..10] of AnsiChar;
  Label4Caption: array [0..10] of AnsiChar;

  MyString: ShortString;


procedure IntToStr(Number: Integer; Str: PAnsiChar);
var
  Digit, Weight: Integer;
begin
  if Number <> 0 then
  begin
    if Number < 0 then
    begin
      Number := -Number;
      Str^ := '-';
      Inc(Str);
    end;
    Weight := 1000000000; //  10^9 <= High(Integer) <= 10^10
    while Number < Weight do
      Weight := Weight div 10;
    while Weight > 0 do
    begin
      Digit := Number div Weight;
      Dec(Number, Weight * Digit);
      Weight := Weight div 10;
      Str^ := AnsiChar(Integer('0') + Digit);
      Inc(Str);
    end;
  end
  else
  begin
    Str^ := '0';
    Inc(Str);
  end;
  Str^ := #0;
end;

// below are some event handlers for our Controls

procedure Button1Click;
begin
  MyString := Text1.Text;
  MyString[Length(MyString) + 1] := #0;
  Label5.Caption := @MyString[1];
end;

procedure Button6Click;
begin
  Label9.Caption := List1.Text;
end;

procedure Button2Click;
begin
  HScroll1.Value := HScroll1.Value + 1;
end;

procedure Button3Click;
begin
  HScroll1.Value := HScroll1.Value - 1;
end;

procedure Button4Click;
begin
  if      Option1.Value then Label7.Caption := 'Option1'
  else if Option2.Value then Label7.Caption := 'Option2'
  else if Option3.Value then Label7.Caption := 'Option3'
  else                       Label7.Caption := 'Nothing';
end;

procedure Button5Click;
begin
  if Check1.Value and Check2.Value then
    Label8.Caption := 'Check1, Check2'
  else if Check1.Value then
    Label8.Caption := 'Check1'
  else if Check2.Value then
    Label8.Caption := 'Check2'
  else
    Label8.Caption := 'Nothing';

  if Check1.Value then
    Text1.Text := 'Check1.Value = True'
  else if Check2.Value then
    Text1.Text := 'Check2.Value = True';

end;

procedure TabStrip1Change;
begin
  case TabStrip1.TabIndex of
    0: List1.SetItems(@ListItemsDays[0], Length(ListItemsDays));
    1: List1.SetItems(@ListItemsCountrys[0], Length(ListItemsCountrys));
    2: List1.SetItems(@ListItemsNumbers[0], Length(ListItemsNumbers));
  end;
end;

procedure Track1Change;
begin
  IntToStr(Slider1.Value, Label1Caption);
  Label1.Caption := Label1Caption;
end;

procedure Track2Change;
begin
  IntToStr(Slider2.Value, Label2Caption);
  Label2.Caption := Label2Caption;
end;

procedure ScrollBar1Scroll;
begin
  IntToStr(VScroll1.Value, Label4Caption);
  Label4.Caption := Label4Caption;
end;

procedure ScrollBar2Scroll;
begin
  IntToStr(HScroll1.Value, Label3Caption);
  Label3.Caption := Label3Caption;
end;


// dont sure where this should be placed
// note that if app launched from the file manager
// than this may be unnecessary
procedure SetApplicationDirectoryAsCurrent;
const
  AppPath: PPAnsiChar = PPAnsiChar(32);
var
  i: LongWord;
begin
  i := 0;
  while AppPath^[i] <> #0 do Inc(i);
  while AppPath^[i] <> '/' do Dec(i);
  AppPath^[i] := #0;
  SetCurrentDirectory(AppPath^);
  AppPath^[i] := '/'; // restore original AppPath
end;

begin
  SetApplicationDirectoryAsCurrent;

// it is possible to Create Window with defined Width & Height centered relative to the screen
//  Window.Create(supCenterScreen, 299, 214, 'GUI2D Example');
// but here used auto sized Window see below

// Create Controls
Label1.Create(56, 280, 57, 25, 'Label1', cbksNormal, cbsNone, Font_Cozette);
Label2.Create(192, 272, 57, 25, 'Label2', cbksNormal, cbsNone, Font_Cozette);
Label3.Create(440, 314, 57, 25, 'Label3', cbksNormal, cbsNone, Font_Cozette);
Label4.Create(354, 360, 57, 25, 'Label4', cbksNormal, cbsNone, Font_Cozette);
Label5.Create(136, 384, 153, 21, 'Label5', cbksNormal, cbsNone, Font_PragmataPro);
Label6.Create(8, 336, 145, 17, 'Enter some words:', cbksNormal, cbsNone, Font_Anka);
Shape2.Create(8, 312, 289, 5, cbksNormal, cbsRaised);
Label7.Create(312, 152, 137, 25, 'Label7', cbksNormal, cbsNone, Font_AnonPro);
Label8.Create(448, 152, 129, 25, 'Label8', cbksNormal, cbsNone, Font_AnonPro);
Label9.Create(164, 192, 137, 25, 'Label1', cbksNormal, cbsNone, Font_PragmataPro);
Picture1.Create(312, 16, 265, 89, cbksNormal, cbsRaised);
Slider2.Create(160, 240, 145, 25, 3, 8, 5);
TabStrip1.Create(8, 8, 291, 28, @TabStrip1Tabs[0], Length(TabStrip1Tabs), Font_Anka);
List1.Create(8, 36, 291, 156, @ListItemsDays[0], Length(ListItemsDays), Font_JBMono);
HScroll1.Create(376, 296, 169, 18, 5, 10, 7, sbHorizontal);
VScroll1.Create(336, 240, 18, 145, 10, 20, 10, sbVertical);
Slider1.Create(8, 240, 145, 25, 13, 30, 20);
Command1.Create(8, 376, 124, 36, 'Check entered', cbksGradient, Font_SCPro);
Command2.Create(368, 256, 92, 36, 'Inc Value', cbksGradient, Font_SCPro);
Command3.Create(464, 256, 92, 36, 'Dec Value', cbksGradient, Font_SCPro);
Text1.Create(8, 353, 164, 21, 'Mytext', Font_PragmataPro);
Command4.Create(312, 112, 136, 36, 'What selected', cbksGradient, Font_SCPro);
Command5.Create(448, 112, 129, 36, 'What checked', cbksGradient, Font_SCPro);
Command6.Create(8, 192, 156, 36, 'What selected in list', cbksGradient, Font_PragmataPro);
Check2.Create(472, 64, 81, 33, 'Check2', cbksGradient, cbsNone, Font_PragmataPro, False);
Check1.Create(472, 24, 81, 33, 'Check1', cbksGradient, cbsNone, Font_PragmataPro, False);
Option3.Create(320, 72, 113, 25, 'Option3', cbksGradient, cbsNone, Font_PragmataPro, False);
Option2.Create(320, 48, 113, 25, 'Option2', cbksGradient, cbsNone, Font_PragmataPro, False);
Option1.Create(320, 24, 113, 25, 'Option1', cbksGradient, cbsNone, Font_PragmataPro, False);

// Create Window centered relative to the screen and fitted to Controls size
  Window.Create(supCenterScreen, asoFitToControls, 'GUI2D Example');

// Set event handlers for control events
  Command1.OnClick := Button1Click;
  Command2.OnClick := Button2Click;
  Command3.OnClick := Button3Click;
  Command4.OnClick := Button4Click;
  Command5.OnClick := Button5Click;
  Command6.OnClick := Button6Click;
  Slider1.OnChange := Track1Change;
  Slider2.OnChange := Track2Change;
  VScroll1.OnScroll := ScrollBar1Scroll;
  HScroll1.OnScroll := ScrollBar2Scroll;
  TabStrip1.OnChange := TabStrip1Change;

// And than 'Run'
  Run;
end.


misc.php?action=pun_attachment&amp;item=173&amp;download=0

Код примера
program GUI2DProject;

uses
  KolibriOS, GUI2D;

const
  ListBox1Items: array[0..11] of PAnsiChar =
    ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');

  TabControl1Tabs: array[0..4] of PAnsiChar =
    ('one', 'two', 'three', 'four', 'five');

  ListBox2Items: array[0..18] of PAnsiChar =
    ('Apple', 'Acer', 'AOC', 'Asus', 'BenQ', 'Dell', 'Fujitsu', 'Hewlett-Packard', 'Iiyama', 'HannStar', 'Lenovo', 'LG', 'MSI', 'NEC', 'Philips', 'Samsung', 'Sharp', 'Sony', 'ViewSonic');
  
  // GroupId for Option controls
  OPTION_GROUP_1 = 1;
  OPTION_GROUP_2 = 2;  
  
  Font_Anka_Coder = './Anka.ppm';    
  
var
  Panel1: TPanel;
  Button1: TButton;
  ListBox1: TTextListBox;
  TrackBar1: TTrack;
  TabControl1: TTabStrip;
  CheckBox1: TCheck;
  RadioButton1: TOption;
  Edit1: TEdit;
  Edit2: TEdit;
  CheckBox2: TCheck;
  ListBox2: TTextListBox;
  RadioButton2: TOption;
  ScrollBar1: TScrollBar;
  ScrollBar2: TScrollBar;
  Button2: TButton;
  RadioButton3: TOption;
  RadioButton4: TOption;
  Panel2: TPanel;

procedure Button1Click;
begin

end;

procedure TrackBar1Change;
begin

end;

procedure TabControl1Change;
begin

end;

procedure ScrollBar1Scroll;
begin

end;

procedure ScrollBar2Scroll;
begin

end;

procedure Button2Click;
begin

end;

// dont sure where this should be placed
// note that if app launched from the file manager
// than this may be unnecessary
procedure SetApplicationDirectoryAsCurrent;
const
  AppPath: PPAnsiChar = PPAnsiChar(32);
var
  i: LongWord;
begin
  i := 0;
  while AppPath^[i] <> #0 do Inc(i);
  while AppPath^[i] <> '/' do Dec(i);
  AppPath^[i] := #0;
  SetCurrentDirectory(AppPath^);
  AppPath^[i] := '/'; // restore original AppPath
end;

begin
  SetApplicationDirectoryAsCurrent;

// create controls
  Panel1.Create(16, 160, 521, 169, cbksNormal, cbsRaised);
  Button1.Create(352, 280, 75, 25, 'Button1', cbksGradient, Font_Anka_Coder);
  ListBox1.Create(152, 16, 121, 106, @ListBox1Items[0], Length(ListBox1Items), Font_Anka_Coder);
  TrackBar1.Create(304, 24, 193, 25, 0, 10, 3);
  TabControl1.Create(216, 176, 305, 25, @TabControl1Tabs[0], Length(TabControl1Tabs), Font_Anka_Coder);
  CheckBox1.Create(424, 64, 105, 17, 'CheckBox1', cbksGradient, cbsNone, Font_Anka_Coder, False);
  RadioButton1.Create(288, 128, 121, 17, 'RadioButton2', cbksGradient, cbsNone, Font_Anka_Coder, False, OPTION_GROUP_1);
  Edit1.Create(152, 128, 121, 23, 'Edit1', Font_Anka_Coder);
  Edit2.Create(16, 128, 121, 23, 'Edit2', Font_Anka_Coder);
  CheckBox2.Create(288, 64, 97, 17, 'CheckBox2', cbksGradient, cbsNone, Font_Anka_Coder, False);
  ListBox2.Create(16, 16, 121, 106, @ListBox2Items[0], Length(ListBox2Items), Font_Anka_Coder);
  RadioButton2.Create(288, 104, 121, 17, 'RadioButton1', cbksGradient, cbsNone, Font_Anka_Coder, False, OPTION_GROUP_1);
  ScrollBar1.Create(24, 176, 121, 16, 50, 70, 50, sbHorizontal);
  ScrollBar2.Create(24, 200, 16, 121, 100, 300, 100, sbVertical);
  Button2.Create(440, 280, 75, 25, 'Button2', cbksGradient, Font_Anka_Coder);
  RadioButton3.Create(416, 128, 121, 17, 'RadioButton3', cbksGradient, cbsNone, Font_Anka_Coder, True, OPTION_GROUP_2);
  RadioButton4.Create(416, 104, 121, 17, 'RadioButton4', cbksGradient, cbsNone, Font_Anka_Coder, False, OPTION_GROUP_2);
  Panel2.Create(411, 100, 3, 49, cbksNormal, cbsRaised);

// set event handlers
  Button1.OnClick := Button1Click;
  TrackBar1.OnChange := TrackBar1Change;
  TabControl1.OnChange := TabControl1Change;
  ScrollBar1.OnScroll := ScrollBar1Scroll;
  ScrollBar2.OnScroll := ScrollBar2Scroll;
  Button2.OnClick := Button2Click;

// create Window
  Window.Create(supCenterScreen, asoFitToControls, 'GUI2D Example');

  Run;
end.


Так как при отрисовке учитываются системные цвета для окон и кнопок, то тёмные скины тоже поддерживаются, например:misc.php?action=pun_attachment&amp;item=170&amp;download=0
 
Прикладываю архив GUI2D_2023.7z с модулем GUI2D.pas и примерами.

Post's attachments

Иконка вложений GUI2D_2023.7z 118.66 Кб, 21 скачиваний с 2023-03-12 

Иконка вложений GUI2D_Test.7z 26.51 Кб, 108 скачиваний с 2021-02-11 

gui2d.gif, 194.71 Кб, 307 x 227
gui2d.gif 194.71 Кб, 136 скачиваний с 2021-02-11 

Иконка вложений SCR_1.PNG 100.22 Кб, 14 скачиваний с 2023-03-12 

Иконка вложений Test0.png 36.94 Кб, 12 скачиваний с 2023-03-12 

Иконка вложений Test1.png 73.39 Кб, 14 скачиваний с 2023-03-12 

Иконка вложений Test2.png 59.5 Кб, 11 скачиваний с 2023-03-12 

10 (изменено: Freeman, 08.06.2023 в 22:19)

Re: Visual Kolibri Library (VKL)

Модератор: обсуждение Git отделено.

Я, кстати, ценю твои наработки по VKL. Не глядя, ибо времени нет. Приятно удивлен, что ты взялся за нее.