【问题标题】:How can I create an internal timer that will work with VCL and FMX?如何创建一个可与 VCL 和 FMX 一起使用的内部计时器?
【发布时间】:2015-12-11 11:31:35
【问题描述】:

我有一个需要计时器的课程。该类必须同时使用 VCL 和 FMX。不幸的是,FMX 定时器在FMX.Types 中声明,VCL 定时器在Vcl.ExtCtrls 中声明。

由于没有像{$IFDEF FMX}xxx{$ENDIF} 这样的条件定义,我如何在跨平台类中使用计时器?

【问题讨论】:

  • @DavidHeffernan - 这是可能的,但我希望能够在任何项目中创建类,而不必担心设置条件定义。
  • @DavidHeffernan - 这在一定程度上会起作用,但如果我测试 Windows,我仍然不知道它是 FMX Windows 还是 VCL Windows。如果我假设它是 VCL 但它是 FMX 应用程序,我将包含 VCL 代码,反之亦然。这是我想要避免的。
  • 啊,我明白了。我当然可以自己写,但我希望有一种更简单的方法可以利用现有代码。
  • @norgepaul 我看不到区分 VCL Windows 或 FMX Windows 的简洁方法,所以我创建了自己的条件定义。然后我在较低级别对其进行测试,以决定是调用 FMX 还是 VCL 例程。事实上,我有一个应用程序是 VCL 应用程序但使用 FMX 表单,因此您可以将两者混合使用,因此没有内置定义的原因。

标签: delphi timer firemonkey vcl delphi-10-seattle


【解决方案1】:

如果是我,我会编写一个独立于 FMX 和 VCL 框架的专用跨平台计时器类。从概念上讲,它将与 Delphi RTL 处于同一级别。

如果您不想这样做并且想重用现有的计时器类,那么您就处于困境中。对于没有 VCL 的目标,你会怎么做?您无法知道您的代码是否会被 FMX 或 VCL 项目使用。想想看。您可以将您的单元编译为 .dcu 并将其包含在任何项目中。在编译单元时,它无法知道最终将使用它的项目类型。

那该怎么办?您可以在任何地方使用 FMX 计时器。但这迫使 FMX 进入 VCL 项目。我知道我不会喜欢那样的。您可以在 Windows 以外的任何地方使用 FMX 计时器,并在那里使用 VCL 计时器。但这会迫使 VCL 进入 Windows FMX 项目。

所以你可能会采取这种方法:

  1. 创建您自己的跨平台计时器类。
  2. 在 Windows 以外的平台上,在 FMX 计时器之上实现它。
  3. 在 Windows 上使用原始 Windows API 函数 SetTimer 和 KillTimer 实现它。

【讨论】:

  • Emba 把一些平台服务放错地方了。 IFMXTimerService 和 IFMXLoggingService 不应属于 FMX。这是更多的 RTL 或只是原始的跨平台。但是您构建一个不依赖于 VCL 或 FMX 的自己的平台框架是正确的。
【解决方案2】:

我们可以假设您的类是非可视的,而且它不是设计时组件。如果不是这种情况,那么它将无法与 FMX 和 VCL 兼容。

在这种情况下,您没有理由不能在 VCL 应用程序中包含 FMX.Types,而且您也没有理由不能在 VCL 应用程序中创建 FMX.Types.TTimer - 您完全可以t 在设计时进行(即:将 FMX TTimer 放在 VCL 表单上)。如果您只需要内部计时器,那么答案很明确 - 只需使用 FMX 计时器,因为无论平台目标或正在使用的框架如何,它都会编译。

unit FMXTimerInVCLApplication;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  FMX.Types;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FTimer : TTimer;   // FMX.Types.TTimer !
    procedure foo(Sender : TObject);
  end;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FTimer := TTimer.Create(nil);
  FTimer.Interval := 1000;
  FTimer.OnTimer := foo;
end;

procedure TForm1.foo(Sender : TObject);
begin
  ShowMessage('foo');
end;

end.

当然,这确实会给您的应用程序带来相当多的 FMX 包袱。如果您关心这类事情,那么计时器会很臃肿。我将其作为其他自然答案(即自己编写)的替代方案。

【讨论】:

  • 当您这样做时,有多少 FMX 单元被拖入您的 VCL 项目?
  • @DavidHeffernan 确实是一堆。
猜你喜欢
  • 2012-01-28
  • 2012-12-16
  • 2014-10-14
  • 1970-01-01
  • 2016-11-28
  • 2014-09-23
  • 1970-01-01
  • 2016-02-17
  • 1970-01-01
相关资源
最近更新 更多