Как создать компонент, поддерживающий как FMX, так и VCL

#delphi #firemonkey #vcl

Вопрос:

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

  1. Как сделать мой компонент совместимым с обоими фреймворками? В идеале я не хочу разделять блок (например, один FMX.myunit.pas и один VCL.MyUnit.pas)
  2. Как сделать так, чтобы мой компонент отображался на панели инструментов только для VCL project или только для FMX project или только для both projects ?
  3. Как в моем dpr/dproj я могу сказать, что мой проект использует платформу VCL или FMX? Может ли проект использовать как фреймворк, так и VCL и FMX?
  4. Для компонентов fmx, почему мне нужно сделать RegisterComponents('myGroup', [TMyControl]); следующее RegisterFmxClasses([TMyControl]); (это выглядит так во всех образцах, которые я видел).

Комментарии:

1. Не ответ на ваш основной вопрос, но… Компонент не рисуется на форме, по крайней мере напрямую. Компонент рисует в своем собственном окне, которое является дочерним окном TForm или другого контейнера.

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

3. @AndreasRejbrand Ты действительно думаешь, что я этого не знаю?

4. @fpiette: Я думаю, вы уже знали об этом, но ваш первый комментарий был не очень точным, поэтому для удобства других людей, читающих этот вопрос, я добавил некоторые детали.

5. «нарисуйте что-нибудь на форме. в основном это точно такой же код..». Возможно, вы можете опубликовать этот код здесь, чтобы кто-нибудь мог разработать для вас решение?

Ответ №1:

Я только что создал компонент, который просто рисует некоторые вещи на T-форме.

Элемент управления пользовательским интерфейсом вообще не должен отображаться в форме. Он должен опираться на Canvas то, что предоставляет ему платформа VCL/FMX, например, в переопределенном Paint() методе.

Как сделать мой компонент совместимым с обоими фреймворками? В идеале я не хочу разделять блок (например, один FMX.myunit.pas и один VCL.MyUnit.pas)

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

Если вы не создадите отдельные блоки для каждой платформы, то вам понадобится IFDEF этот блок по мере необходимости при использовании кодирования для конкретной платформы.

Если вы пишете код, не зависящий от фреймворка, то для обоих фреймворков можно использовать один пакет. Но если вам нужно написать код для конкретной платформы (т. Е. Из-за кода пользовательского интерфейса и т. Д.), Вам нужно будет создать отдельные пакеты для каждой платформы.

Что касается самого компонента, если вы идете по маршруту IFDEF, то, если возможно, попробуйте вывести свой компонент из базового класса, существующего в обеих системах.

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

Для визуальных элементов управления, производных TControl или потомков по мере необходимости. Просто обратите внимание, что существуют различия в том, как каждая платформа реализует визуальные элементы управления, поэтому вам, скорее всего, потребуется IFDEF соответствующий код реализации или использовать отдельные модули для каждой платформы.

Как сделать так, чтобы мой компонент отображался в палитре инструментов только для проекта VCL или только для проекта FMX или для обоих проектов ?

Пакет может иметь сходство с определенной структурой (см. Далее ниже).

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

Когда вы регистрируете элемент управления пользовательского интерфейса, вы должны позвонить GroupDescendentsWith() , чтобы сгруппировать свой элемент управления в TControl группу классов, например:

 RegisterComponents('My Control', [TMyControl]);
GroupDescendentsWith(TMyControl, TControl);
 

Не полностью уточняйте область действия единицы измерения TControl ни в этом вызове , ни в вашем uses предложении. Используйте только Controls модуль и позвольте компилятору выбирать между FMX.Controls.TControl или Vcl.Controls.TControl в зависимости от того, какая версия TControl доступна, в зависимости от того, для какой платформы компилируется ваш пакет.

Как в моем dpr/dproj я могу сказать, что мой проект использует платформу VCL или FMX?

В .dproj , во-первых <PropertyGroup> , есть доступный <FrameworkType> элемент (добавьте его, если он отсутствует), который может быть установлен в VCL , FMX , или None .

Может ли проект использовать как фреймворк, так и VCL и FMX?

Официально-нет. Но есть неофициальные способы (т. е. сторонние решения) сделать это. Я бы не рекомендовал делать это внутри пакета, только внутри приложения.

Для компонентов fmx, почему мне нужно сделать RegisterComponents('myGroup', [TMyControl]); следующее RegisterFmxClasses([TMyControl]); (это выглядит так во всех образцах, которые я видел).

Все, что на самом деле делается, — это группировка TMyControl в группу TFmxObject классов, которая доступна только тогда, когда активна платформа FMX. Это просто еще одна группа, используемая для фильтрации отображения компонентов в интегрированной среде разработки. Группировка элемента управления пользовательского интерфейса в группу TControl классов выполняет то же самое.