Delphi XE2: есть ли предопределенное условие для идентификации VCL и FireMonkey?

В Delphi XE2 мы используем

{$ifdef Win32}
{$ifdef Win64}

чтобы определить, на какой платформе мы находимся.

Есть ли какие-либо предопределенные условия, которые могут идентифицировать VCL и FMX?


person Chau Chee Yang    schedule 11.10.2011    source источник
comment
Нет, вы должны определить свое собственное.   -  person jed    schedule 11.10.2011
comment
Зачем это нужно? Что-то мне кажется немного подозрительным.   -  person David Heffernan    schedule 11.10.2011
comment
кто-то может захотеть использовать модуль с общей функциональностью как в vcl, так и в fmx приложениях, ничего подозрительного в этом нет. например: Использует {$ IFDEF FMX} FMX.Forms {$ ELSE} Vcl.Forms; {$ ENDIF}   -  person Tuncay Göncüoğlu    schedule 09.12.2015


Ответы (6)


Как говорят другие, нет условной директивы, определяющей, является ли ваше приложение VCL или FireMonkey. Я думаю, что самый надежный способ определить, является ли ваше приложение FireMonkey или VCL, - это использовать функцию вместо условной директивы.

Что-то вроде

Uses
 Rtti;

function IsVCLApp:Boolean;
begin
 Result:= CompareText(TRttiContext.Create.GetType(TApplication.ClassInfo).QualifiedName,'Vcl.Forms.TApplication')=0;
end;

function IsFireMonkeyApp:Boolean;
begin
 Result:= CompareText(TRttiContext.Create.GetType(TApplication.ClassInfo).QualifiedName,'FMX.Forms.TApplication')=0;
end;
person RRUZ    schedule 11.10.2011
comment
@Craig, очевидно, этот код требует, чтобы был добавлен блок форм, о том, в какой области вам не нужно добавлять VCL. или FMX. это решается внутри delphi. Так что, если вы используете Formsили Vcl.Forms, код будет работать нормально. И, наконец, о вашем последнем комментарии, который зависит от типа приложения, этот ответ предлагает использовать функцию в качестве альтернативы использованию conditional directive. - person RRUZ; 11.10.2011
comment
Этот код требует использовать Forms, а не Vcl.Forms. Если вы явно используете Vcl.Forms или Fmx.Forms, то вы уже определились с платформой в разделе uses для модуля и, следовательно, уже имеете условный способ проверки целевого набора виджетов. - person Zoë Peterson; 11.10.2011
comment
Кроме того, поскольку TApplication, о котором вы говорите, не может измениться во время выполнения, использование TRttiContext совершенно не требуется. Вы можете упростить IsFireMonkeyApp до Result := {$IF DECLARED(TFmxObject)}True{$ELSE}False{$IFEND};, и он будет вести себя точно так же. - person Zoë Peterson; 11.10.2011
comment
Лучше изменить указанное выше на Result := GetClass('TFmxObject') <> nil;, поскольку для этого не требуется FMX.Types - это область действия. - person da-soft; 06.05.2012

Хотя это не задокументировано, вы можете использовать VCL и Firemonkey в одном приложении.

Нет определения компилятора.

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

Возможный способ:

  • MyLibrary.X.pas - Общий код, который будет использовать как VCL, так и Firemonkey.
  • MyLibrary.Vcl.X.Pas - специальный код Vcl
  • MyLibrary.Fmx.X.Pas - специальный код для FMX

Смешивание кода пользовательского интерфейса из двух разных фреймворков в одном модуле - не лучшая идея. Он будет связываться с другой библиотекой, когда в ней нет необходимости.

person Robert Love    schedule 11.10.2011

Директивы компилятора нет, потому что технически не существует таких вещей, как приложение firemonkey или приложение vcl. Только приложения, использующие эти технологии. Приложение может использовать fxm или vcl, либо оба, либо ни то, ни другое (например, консольное приложение). Это немного похоже на вопрос, является ли это приложением SQL. Конечно, вы можете программно проверять происхождение отдельных форм, чтобы увидеть, от какой структуры они наследуются. Опять же, внутри единицы, не имеющей связанной формы, это не имеет значения.

person Peter    schedule 25.10.2011

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

Список предопределенных условных операторов можно найти в документации.

person Bruce McGee    schedule 11.10.2011
comment
Проверка определения платформы ненадежна, потому что вы можете создать, например, приложение OSX с GUI without Firemonkey, как показано здесь stackoverflow.com/questions/7442131/ - person RRUZ; 11.10.2011
comment
@RRuz: Достаточно честно. Отредактировал свой ответ. - person Bruce McGee; 11.10.2011

Abbrevia поддерживает как VCL, так и CLX с использованием такого разделения:

QAbUnit1.pas:

{$DEFINE UsingCLX}
unit QAbUnit1;
{$I AbUnit1.pas}

AbUnit1.pas:

{$IFNDEF UsingCLX}
{$DEFINE UsingVCL}
unit AbUnit1;
{$ENDIF}

type
  ...
  TMyWidget = class({$IFDEF UsingVCL}TWinControl{$ENDIF}
                    {$IFDEF UsingCLX}TWidgetControl{$ENDIF})
  ...
  end;

end.

Чтобы добавить поддержку FireMonkey, я бы добавил такой файл:

FmxAbUnit1.pas:

{$DEFINE UsingFMX}
unit FmxAbUnit1;
{$I AbUnit1.pas}
{$ENDIF}

а затем внесите необходимые условные изменения в AbUnit1.pas.

Это не очень хорошее чистое разделение, как предложение Роберта, но преимущество состоит в том, что все ваше редактирование происходит в одном файле, а условное определение обрабатывается автоматически, поэтому его не нужно указывать в параметрах проекта. Кто когда-либо использует вашу библиотеку, просто включает соответствующий модуль, чтобы решить, какой из них они хотят использовать. Вы, вероятно, могли бы также воспользоваться преимуществом определения области видимости, назвав файлы Fmx.AbUnit1.pas и Vcl.AbUnit1.pas, но я думаю, что Embarcadero не одобряет этого.

person Zoë Peterson    schedule 11.10.2011
comment
Довольно красивое решение. Но справляется ли Help insight с этой конструкцией при определении FMX? По крайней мере, в XE2 он становится беспомощным при редактировании включенных файлов. - person Fr0sT; 05.09.2014
comment
@ Fr0sT Я не использую FMX, поэтому не могу сказать. В XE1 простые тесты работают, но они собирают только некоторые изменения в модуле после того, как я закрываю и снова открываю проект. - person Zoë Peterson; 05.09.2014

Попробуйте этот фрагмент:

{$IF Declared(FMX)}
  // FMX code here. To test this approach you may use {$MESSAGE FATAL 'FMX'}
{$ELSEIF Declared(VCL)}
  // VCL code here. To test this approach you may use {$MESSAGE FATAL 'VCL'}
{$IFEND}

Он проверяет, было ли объявлено соответствующее пространство имен с использованием директива компиляции IF

Поскольку FMX не является взаимоисключающим с VCL, может потребоваться добавить следующие ветки:

{$ELSEIF Declared(FMX) and Declared(VCL)}
  // FMX+VCL code here. To test: {$MESSAGE FATAL 'FMX+VCL'}
{$ELSE}
  // no GUI frameworks code here. To test: {$MESSAGE FATAL 'no GUI frameworks'}
person Serhii Kheilyk    schedule 03.12.2019