В этой статье я покажу, что из себя представляет фреймворк FireMonkey, на что он способен и в чем его основная идея. Подробно рассматривать технические отличия от VCL не буду, но некоторых вещей обязательно коснусь. Прошу не судить строго за статью, я постараюсь следить за ошибками в тексте и постараюсь донести свою мысль. Также, знаю, как сейчас относятся к Delphi, но тем не менее статья именно о нём. И первым делом, хотелось бы немного об этом поговорить. 

Язык и среда разработки активно развиваются. Местами не так активно или не в том направлении, в котором некоторые ожидают, но мы регулярно видим обновления (~каждые 3 месяца).

Вот некоторые из последних и значимых обновлений:

Среда разработки

  • Поддержка LSP - Language Server Protocol

    • Это позволило создать плагин подсветки и анализа кода в VS Code

    • Новое API для плагинов IDE, работающих с кодом

  • Добавили HiDPI для среды. Обновили всю графику

    • Среда корректно может работать с HiDPI на разных мониторах с разным DPI

    • В среде можно тестировать HiDPI для созданных форм (вручную можно указать в дизайнере целевой DPI)

    • Некоторые компоненты VCL имеют возможность добавлять несколько вариантов растровой графики, которая будет выбираться в зависимости от масштабирования формы

  • Встроенный менеджер пакетов GetIt

    • В проекте можно указать зависимости, которые будут скачаны и установлены автоматически, если отсутствуют

    • Там же публикуются обновления среды (патчи)

  • Вынос вкладок с кодом или дизайнером в отдельные окна

  • SplitView редактора (этот и предыдущий пункт позволяют редактировать один и тот же файл параллельно)

  • Среда избавилась от WebView, который использовался для WelcomePage и справочной информации при работе с кодом, теперь используется движок на базе HTMLComponents

  • Обновление системы стилей VCL

    • VCL теперь может использовать разные “скины” для отдельных контролов

    • Стиль отображается не только в рантайм, но и в дизайн тайм

  • Затемнение кода, который сейчас не учитывается из-за условных директив

  • Подсветка блоков в редакторе, подсветка синтаксиса ассемблерных вкладок, подсветка ассемблера в отладочных окнах, направляющие в дизайнере

  • Цветовое разделение элементов в окне Сообщений, Дереве структуры кода, в поиске по методам и классам

  • Более отзывчивое и функциональное окно автозавершения кода и подсказок

  • Индикация внутри скроллбара (места ошибок, подсказок, варнингов, изменений и т.д.)

  • Стилизация IDE и режимы темный/светлый

  • Focus Mode - режим фокусировки на написании кода (по сути, просто "F11" для редактора кода)

Язык

  • Инлайн объявление переменных

var MyInt: integer := 1;
...
for var i := 0 to 10 do ...
  • Выведение типов

var i := 1;
...
for var Item in List do
...
for var Control in Layout.Controls do 
...
var text := GetText();
...
var Proc := 
  procedure(i: integer)
  begin
    ...
  end;
Proc(123);
  • Директива inline для оптимизации вызовов методов

  • Классовые конструкторы/деструкторы

  • Конструкторы/деструкторы записей (Managed Records)

    • На их основе можно делать более простые смартпоинтеры

  • Поддержка инструкций AVX-512

  • Некоторые мелочи по типу записи числа в бинарном виде (%101110), или с разделителями тысячных (1_000_000)

  • Мультистроки (ссылка)

var Query := '''
  SELECT * FROM table
  WHERE field = :my_value
  ''';
  • Анонимные функции и захват переменных (захватываются адреса)

  • Дженерики (обобщенные типы)

    • С ними полезные вещи:

      • TValue - тип, схожий с Variant, но имеющий более удобные инструменты присваивания и получения значения (AsType<T>, Form<T>, ...)

      • Метод Default(T) - позволяет инициализировать переменную обобщенного типа значением "по умолчанию"

  • TArray<T> и конкатенация массивов

Это наиболее интересные, на мой взгляд, обновления за полтора года (и чуть раньше). Patch Notes на самом деле включает в себя списки фиксов (до нескольких сотен за раз), обновления RTL и т.д.

Ещё ссылки:
Изменения в D12
Изменения в остальных версиях

FireMonkey (FMX)

Данный фреймворк позволяет создавать графические приложения под следующие платформы: MS Windows (32/64bit), Linux (64bit), MacOS (64bit, ARM 64bit), Android (32/64bit), iOS (64bit, simulator ARM 64bit). А прежде чем начнем рассматривать FMX, давайте посмотрим на современную версию среды разработки Delphi.

RAD Studio Delphi 12
RAD Studio Delphi 12

Тут мы видим новый, кастомизируемый WelcomePage и в окне Create New пункт создания кроссплатформенного приложения - Multi-Device Application.
P.S. для WelcomePage мы можем создавать собственные представления и добавлять их на экран.

Шаблоны Multi-Device Application
Шаблоны Multi-Device Application

В этой статье будем использовать только пустое приложение - Blank Application. Выбираем его, после чего создается проект и открывается вкладка с первым модулем и дизайнером окна (всё как в VCL). 

Быстро пройдемся по окну среды:

  1. Выбор активной платформы и целевого устройства или эмулятора

  2. Текущий отображаемый стиль (платформа) в дизайнере и вариант окна (интерфейс можно отдельно настроить под разные устройства/размеры экранов)

  3. Управление проектом, тут мы можем выбрать или добавить платформу, указать конфигурацию сборки (Debug/Release), настроить пакеты и библиотеки (например, для Андроид) и использовать как навигацию по проекту.

  4. Дизайнер окна

Дальше всё как обычно: Инспектор объектов, Дерево объектов, Палитра компонентов. Но, в целом, отличий не так много от VCL.

Теперь, приступим. Возьмем два простых элемента: кнопку и слой/контейнер (layout). Layout - это абсолютно пустой контрол, который обычно используется для разметки.

В Layout поместим другие элементы. Например, Label, Rectangle и Image. У Layout найдем свойство StyleName и зададим значение, например “my_button”. А у кнопки найдём свойство StyleLookup и укажем то же значение. Увидим следующую картину:

Наша кнопка стала отображаться так, как мы настроили наш Layout. В окне структуры (слева вверху) мы видим, что кнопка внутри себя не содержит ничего, но выглядит точно так же, как наполненный Layout, а элементы подчиняются выравниванию относительно размеров кнопки. Если мы зададим компоненту Label в слое свойство StyleName = “text”, то кнопка подхватит наличие этого элемента и будет отображать там свой текст. Помимо этого кнопка установит свои настройки текста (в данном случае выравнивание по центру) для Label

Сейчас, если запустить приложение, кнопка будет “некликабельная”, т.к. все нажатия перехватывают помещенные в слой компоненты, но это можно исправить, установив им свойство HitTest в значение False.
Конечно, мы потеряли всю анимацию при наведении и при нажатии на кнопку, т.к. мы всеми этими действиями указали собственный стиль компонента, заменив стиль “по умолчанию”. В будущем мы это исправим.

Вот таким простым способом мы можем менять представление любого компонента. Но, оставлять на форме “шаблон” не очень удобно, по этому, добавим на форму компонент TStyleBook. Двойным кликом его откроем. Теперь мы можем вырезать наш шаблон с формы и вставить в структуру слева:

Окно дизайнера стиля (StyleBook)
Окно дизайнера стиля (StyleBook)

Добавленный компонент StyleBook нужно указать в одноименное свойство формы и наш стиль снова будет доступен кнопке, но уже из StyleBook.

StyleBook

Немного рассмотрим компонент StyleBook. Этот компонент имеет свой дизайнер.

  1. Структура стилей - основной способ навигации по списку стилей. В этой структуре отображается StyleName, а не Name элемента

  2. Целевая платформа стиля. Default - стиль по умолчанию для всех платформ.

  3. Вариант отображения фона

  4. Кнопка “Применить”. Её нужно не забывать нажимать.

  5. Превью стиля (тут работают события мыши для стиля. Среда разработки подбирает контрол для превью по имени стиля)

В этом дизайнере мы можем настроить стиль нужного нам контрола почти так же, как в обычном дизайнере формы. Нам доступны все те же компоненты из палитры компонентов. Мы можем добавить также анимацию, эффекты и прочее. 

Анимация свойств
Анимация свойств

Я добавил две анимации TFloatAnimation, которые анимируют свойство Opacity у фона bg: TRectangle. В анимации указаны триггеры (могут быть: IsMouseOver, IsPressed, IsOpen, IsChecked, isVisible, ...), на которые анимация будет срабатывать, само свойство и значения, в пределах которых будет изменяться свойство. Это значит, что при наведении мыши фон будет становиться чуть прозрачным, а при нажатии или отводе мыши возвращаться обратно.

Таким образом мы можем анимировать любые свойства контрола (Opacity, Margins, Paddings, Size, Position и т.д.). А помимо TFloatAnimation имеются следующие, готовые аниматоры:

TColorAnimation - анимация цвета интерполяцией
TGradientAnimation - анимирует цвета точек градиента (тоже интерполяцией)
TFloatAnimation - анимирует любое свойство с типом Single
TRectAnimation - комплексная анимация свойств с типом TRectF
TBitmapAnimation - анимация смены картинки
TBitmapListAnimation - покадровая анимация (как для Sprite)
TColorKeyAnimation/TFloatKeyAnimation - анимации с несколькими значениями по временным меткам
TPathAnimation - анимация, использующая в качестве значений PathData (как в SVG), т.е. позволяет описать траекторию изменения значения

Помимо подобных анимаций, существуют TransitionEffect анимации, использующие шейдеры. Позволяют анимировать смену или изменение растрового изображения различными способами, либо добавить какой-то переходной эффект. Такими анимациями можно реализовать смену StyleBook. Например, если имеется два StyleBook для темной и для светлой темы.

Один из моих старых примеров смены стиля через TransitionEffect.

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

Мы можем создавать стили в том числе и для элементов списка TListBox и дерева TTreeView, можем назначать разным элементам разные стили и размеры, что значит, что они могут быть сколько угодно сложным. Стилизации поддается абсолютно всё (на самом деле, почти всё, но по этому поводу уже созданы issue для исправления), что позволяет нам кардинально менять вид нашего приложения.

Пример
Помощник в создании десериализации Json to Delphi в стиле MaterialDesign 3
Помощник в создании десериализации Json to Delphi в стиле MaterialDesign 3
Помощник в создании десериализации Json to Delphi в стиле WinUI 3 + Mica оформление окна
Помощник в создании десериализации Json to Delphi в стиле WinUI 3 + Mica оформление окна

Продолжение следует.

UPD

Для тестов и своих проектов можно взять бесплатную коммьюнити версию, вышедшую на прошлой неделе тык

Комментарии (23)


  1. kia00000
    05.08.2024 09:10
    +1

    паскаль не так плох чтобы его выбрасывать


  1. Seenkao
    05.08.2024 09:10
    +4

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

    Из книг (многие подустарели, но актуальной информация, думаю, остаётся по сей день):

    • Дмитрий Осипов "Delphi XE2", 2012

    • Всеволод Леонов "Обучение мобильной разработке на Delphi", 2014-1015

    • Рубанцев Валерий "Большой самоучитель Delphi XE3", 2013

    • Дмитрий Осипов "Delphi. Программирование для Windows, OS X, iOS и Android", 2014

    Была вроде недавно какая-то книга выпущена, но уже не помню какая.


    1. boulat
      05.08.2024 09:10
      +2

      вот это охуенно:
      Многопоточное программирование в Delphi для начинающих
      Автор: Логинов Д.С.
      https://github.com/loginov-dmitry/multithread/blob/master/multithread_in_delphi_for_beginners.md


    1. Twilizer
      05.08.2024 09:10
      +1

      Обучение мобильной разработке на delphi всеволод леонов 2-e издание. Интересная книга по разработке андроид приложений на delphi.


    1. Groramar
      05.08.2024 09:10
      +1

      Заходите в телеграмм-чаты, один из них https://t.me/Delphi_Lazarus, людей хватает, постоянно какой-то движ в чате


  1. Vottakonotak
    05.08.2024 09:10

    Как работает под линуксом? Для альт линукс приложения можно делать?


    1. HemulGM Автор
      05.08.2024 09:10
      +1

      Можно. Корректно работает на многих дистрибутивах. Мои личные тесты: Убунту, Арч, Гаруда, Минт, Астра (вроде Смоленск)


      1. kalapanga
        05.08.2024 09:10
        +1

        Я правильно понимаю, что эта возможность появляется только начиная с редакции Enterprise?

        Delphi Feature Matrix - Features - Embarcadero


        1. HemulGM Автор
          05.08.2024 09:10

          Как бы то ни было странно, да. Линукс у них считает корпоративным сегментом, по этому только редакции Enterprise и выше


        1. Seenkao
          05.08.2024 09:10
          +2

          Если уж совсем приспичит использовать Linux, то используй FPC/Lazarus.

          Только FireMonkey там не будет.


    1. Groramar
      05.08.2024 09:10
      +2

      Делаем и подаём вполне успешно. Перенесены с VCL на Унигуй/Linux


  1. Naf2000
    05.08.2024 09:10

    А в Delphi уже есть деревья выражений как в .net (но без .net)?


    1. HemulGM Автор
      05.08.2024 09:10

      Лямбда как таковых нет, только анонимные функции и процедуры. А лямбды я так понимаю их часть. Так что, вероятно ответ нет. Или может я не так понимаю "деревья выражений".


  1. ChessMax
    05.08.2024 09:10

    Было бы интересно узнать про отличия VCL от FireMonkey. А также плюсы и минусы последнего.


    1. HemulGM Автор
      05.08.2024 09:10
      +2

      Коснусь этого, когда буду писать вторую часть.

      На самом деле, отличается кардинально. Все контролы полностью реализованы на Делфи и соответственно платформонезависимые, однако, некоторые контролы являются "presentable", т.е. имеют общую модель данных, но могут иметь разные представления (реализации). А именно: fmx-реализацию (как и другие контролы) и нативную реализацию. Например, TEdit может быть как чисто fmx, а может быть виндовым нативным или андроид нативным.

      Когда контрол для разных платформ имеет разную реализацию - это тот же LCL из Lazarus. В fmx же разная нативная реализация - лишь опция для некоторых контролов.

      В VCL каждый контрол - отдельное окно и отдельный канвас. В fmx, только один общий канвас. Конечно, если контрол не переключен в режим "нативность". Но это исключение, опция. Мало кто этим пользуется. Потому что, если контрол нативный и имеет свой канвас, значит он находится над общим канвасом и всегда будет поверх остальных не нативных контролов.

      В fmx контрол - лишь набор данных и событий. При первом появлении на "сцене", контрол запрашивает свое представление. Как правило это стиль из пула стилей. Стиль может состоять из чего угодно, но в конечном итоге - это графические примитивы, которые и рисуются. Каждый контрол, при применении стиля или изменении своих данных, ищет внутри стиля "особые" элементы. Например, кнопка будет искать элемент текстового типа с названием "text", куда будет передавать значение из своего свойства "Text" (подпись кнопки) и настройки текста этой кнопки.

      Однако, никто не запрещает с стиле иметь и другие элементы, о которых кнопка не знает. А ко всем элементам стиля каждого контрола можно обращаться из кода.

      Всё это позволяет убрать ограничения на то, как контрол будет выглядеть и даже на то, что может контрол изначально. Внутрь стиля кнопки мы можем поместить контрол кнопки и будет кнопка в кнопке (SplitButton). К внутренней кнопке мы тоже можем обращаться и назначать свойства и события.

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

      Теперь мы можем без проблем делать любую полупрозрачность, т.к. канвас у нас один.

      А т.к. в fmx окно по умолчанию "слоистое" в Винде, то мы можем убирать фон окна при этом оставляя полупрозрачность элементов окна. Мы можем даже 3D сцену иметь без фона и рисовать 3D объекты как они есть (Wallpaper Girl 3D теперь очень легко делать =)).

      Терпеть, т.к. у нас только у окна есть Handle - только оно может получать события от винды. И именно окно генерирует события для контролов.

      Другими словами, fmx ближе к графическим движкам, типа Unity.

      Канвас, в fmx, кстати тоже имеет разные реализации. Несколько реализаций для винды и по 1-2 для других платформ. Канвас может быть d2d, directx, opengl, opengles, opengl (иосовский), metal, skia и т.д.


      1. ChessMax
        05.08.2024 09:10

        Спасибо, интересные нюансы. Не знал о них.


        1. HemulGM Автор
          05.08.2024 09:10

          Их ещё много, но я устал писать с телефона


  1. zloyreznic
    05.08.2024 09:10

    Delphi еще жив? последний раз о нем слышал в 2010


    1. Twilizer
      05.08.2024 09:10

      Delphi жив и развивается, вдобавок на нём даже все ещё работают и есть компании которые ищут себе сотрудников. Плюс в сам язык вносят множество вещей. Появилась(но уже давно) разработка под IOS и Android


    1. HemulGM Автор
      05.08.2024 09:10

      Некогда ему умирать. Да и регулярные обновления, вебинары, нововведения и прочее, не дают.


    1. v1ctar
      05.08.2024 09:10

      zloyreznic еще жив? никогда не слышал о нём :-)


      1. zloyreznic
        05.08.2024 09:10

        юмор за 100


        1. v1ctar
          05.08.2024 09:10

          соотвествуем вопросу :-)