【问题标题】:Delphi XE2: Is there a predefined conditional to identify VCL and FireMonkey?Delphi XE2:是否有预定义的条件来识别 VCL 和 FireMonkey?
【发布时间】:2011-12-04 22:49:59
【问题描述】:

在Delphi XE2中,我们使用了

{$ifdef Win32}
{$ifdef Win64}

确定我们所处的平台。

是否有任何可以识别 VCL 和 FMX 的预定义条件?

【问题讨论】:

  • 不,你应该自己定义。
  • 为什么需要这个?我闻起来有点腥。
  • 人们可能想在 vcl 和 fmx 应用程序中使用具有通用功能的单元,这没什么可疑的。比如:使用 {$IFDEF FMX} FMX.Forms {$ELSE} Vcl.Forms;{$ENDIF}

标签: delphi delphi-xe2 firemonkey


【解决方案1】:

虽然没有记录,但您可以在同一个应用程序中使用 VCL 和 Firemonkey。

没有编译器定义。

如果您要构建的东西既需要 VCL 又需要 Firemonkey,我建议将单元分开。

一种可能的方式:

  • MyLibrary.X.pas - VCL 和 Firemonkey 都将使用的公共代码。
  • MyLibrary.Vcl.X.Pas - Vcl 特定代码
  • MyLibrary.Fmx.X.Pas - Fmx 特定代码

在同一个单元中混合来自两个不同框架的 UI 代码不是一个好主意。它会在不需要时链接到其他库中。

【讨论】:

    【解决方案2】:

    正如其他人所说,没有条件指令来确定您的应用程序是 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;
    

    【讨论】:

    • @Craig,显然此代码要求必须添加表单单元,关于您不需要添加“VCL”的范围。或“FMX”。这是由delphi内部解决的。因此,如果您使用 FormsVcl.Forms 代码将正常工作。最后,关于您最后一条取决于应用程序类型的评论,此答案建议使用函数来替代使用 conditional directive
    • 此代码要求您使用Forms 而不是Vcl.Forms。如果您明确使用Vcl.FormsFmx.Forms,那么您已经在该单元的uses 子句中确定了平台,因此已经有条件检查目标小部件集。
    • 此外,由于您所指的 TApplication 在运行时无法更改,因此完全不需要使用 TRttiContext。您可以将IsFireMonkeyApp 简化为Result := {$IF DECLARED(TFmxObject)}True{$ELSE}False{$IFEND};,它的行为完全相同。
    • 最好将上面的内容更改为Result := GetClass('TFmxObject') <> nil;,因为这不需要FMX。类型是范围。
    【解决方案3】:

    没有编译器指令,因为技术上不存在 firemonkey 应用程序或 vcl 应用程序之类的东西。只有使用这些技术的应用程序。 应用程序可以使用 fxm 或 vcl 或两者都使用或都不使用(例如控制台应用程序)。 这有点像询问它是否是一个 SQL 应用程序。您当然可以以编程方式检查各个表单的祖先,以查看它们继承自哪个框架。 同样,在没有关联形式的单元中,这没有任何意义。

    【讨论】:

      【解决方案4】:

      似乎没有专门为 VCL/FireMonkey 定义的编译器。您需要创建自己的。

      可以在documentation 中找到预定义条件列表。

      【讨论】:

      • 检查平台定义是不可靠的,因为您可以使用GUI without Firemonkey 创建例如一个 OSX 应用程序,如下所示stackoverflow.com/questions/7442131/…
      • @RRuz:很公平。编辑了我的回复。
      【解决方案5】:

      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.pasVcl.AbUnit1.pas 来利用单元范围,但我认为 Embarcadero 不鼓励这样做。

      【讨论】:

      • 相当不错的解决方案。但是,当定义 FMX 时,Help insight 会处理这种构造吗?至少在 XE2 中,它在编辑包含的文件时会变得无能为力。
      • @Fr0sT 我不使用 FMX,所以我不能说。在 XE1 下,简单的测试可以工作,但它只是在我关闭并重新打开项目后才对单元进行一些更改。
      【解决方案6】:

      试试这个 sn-p:

      {$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 compilation directive 声明了相应的namespace

      由于 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'}
      

      【讨论】:

        猜你喜欢
        • 2011-12-31
        • 2023-03-11
        • 1970-01-01
        • 2013-10-26
        • 2011-11-19
        • 1970-01-01
        • 1970-01-01
        • 2011-12-08
        • 1970-01-01
        相关资源
        最近更新 更多