Delphi XE2:在VCL应用程序中实例化FireMonkey表单是否可能?

25
在 Delphi XE2 之前,我们只能使用 VCL 创建 GUI 应用程序。Delphi XE2 指出:

注意:FireMonkey (FMX) 和 Visual Component Library (VCL) 不兼容,并且不能在同一项目或应用程序中使用。也就是说,应用程序必须完全使用其中一种,即 FireMonkey 或 VCL。不兼容性是由于 FireMonkey (FMX) 和 VCL 之间的框架差异造成的。

我的应用程序是一个纯 VCL 应用程序,使用运行时包构建。所有的 VCL 窗体都存储在一个运行时包中。如果我要创建一个 FireMonkey 窗体并存储在一个包中,我有没有任何机会在我的 VCL 应用程序中动态地实例化这个 FireMonkey 窗体?这样我就可以享受 FireMonkey 提供的 3D 或 HD 效果了。

1
我怀疑这将永远不可行,而且你为什么要这样做呢?VCL是Windows特定的光栅图形和带有Windows句柄的控件,而FireMonkey是跨平台矢量图形和没有句柄的控件。两者的应用框架非常不同。请选择其中一个。 - Misha
2
@Dorin Duminica:新的跨平台FireMonkey库中的错误(这是我主要听到的错误报告)在某种程度上是不可避免的。据我所知,Win32编译器和VCL与以往一样强大。当然,在向客户发布FireMonkey应用程序之前,我会等待一个或两个更新包,但就个人而言,我将利用这段时间来熟悉FireMonkey,并使用最新和最好的Win32编译器和VCL来维护我的现有应用程序。 - LachlanG
3
我很惊讶“高清”这个市场营销词汇如此迅速地传播开来…… - jpfollenius
全局类(如TApplication)怎么样?我猜FireMonkey有自己的TApplication实例。它们可能不会混合在一起。 - Lars Truijens
在XE7中尝试了一下,但运气不太好。当然,我可以在VCL应用程序中创建和使用FMX表单。一个非常基本的空表单。但是,当我关闭我的应用程序时,我会收到无尽的访问冲突和其他异常,以及主要的内存泄漏问题。 - Jerry Dodge
显示剩余3条评论
6个回答

25
这是完全可能的,因为FMX表单可以分配到面板上。
请参见这篇博客文章了解详情:链接

只需创建一个新的FireMonkey表单(2D或3D都可以),保存它,然后将其添加到您的VCL应用程序中(只需接受警告)。您可以在其他地方创建您的FMX表单实例,然后显示它 - 没问题。但是,如果您想创建一些带有动画或其他东西的漂亮控件,并将其嵌入到现有的VCL表单中呢?好吧,在您的VCL表单上放置TPanel并在Vcl.ExtCtrls之后包含全新的单元DSharp.Windows.FMXAdapter.pas。然后在其他地方创建您的FMX表单并将其分配给Panel的新Form属性--就这样。

事实上,FMXAdapter.pas代码非常简短:
procedure TPanel.Resize;
begin
  inherited;
  ResizeForm();
end;

procedure TPanel.ResizeForm;
begin
  if Assigned(FForm) then
    Platform.SetWindowRect(FForm, RectF(BorderWidth, BorderWidth,
      ClientWidth + BorderWidth, ClientHeight + BorderWidth));
end;

procedure TPanel.SetForm(const AForm: TCommonCustomForm);
begin
  FForm := AForm;  
  FForm.BorderIcons := [];
  FForm.BorderStyle := TFmxFormBorderStyle.bsNone;
  ResizeForm();
  FForm.Visible := True;
  Winapi.Windows.SetParent(FmxHandleToHWND(FForm.Handle), Handle);
end;

正如[XE2的博客评论]文章所述,即使IDE似乎在其VCL表单中嵌入了一些FireMonkey组件:“Spy ++说整个东西只是一个窗口,类别为FMTStyleDesigner。”因此,这绝对是肯定的。 - Arnaud Bouchez
1
@Arnaud:链接似乎无法使用 - 它应该是指http://itinerantdeveloper.blogspot.com/2011/09/c-builder-xe2.html吗? - David

6
为了更现代的方法,可以尝试使用TFireMonkeyContainer。它是一个开源的VCL组件,可以放置在VCL表单上,并且可以在其中托管/嵌入FireMonkey表单。
详情请查看:介绍文章更新文章,包括一些错误修复和更多功能。在这里找到链接到Google Code页面和源代码
它适用于XE2及以上版本,包括XE4+(其中FMX有一些重大变化)。
免责声明:这是我的组件。(我创建它来解决这个问题。)它是MPL许可,因此即使在商业应用程序中也可以自由使用。希望它能帮助您并使您的生活更轻松!

我在 Delphi XE7 中使用它,它运行得非常好。现在我获取了适用于 Delphi 10 Seattle 的最新版本,但可悲的是它无法正常工作。起初似乎可以工作,但当我点击某些东西时,一切都会冻结。 - Jerry Dodge
到目前为止,它似乎与触发TChangeTabAction的点击有关。在其他地方点击目前为止似乎工作正常。将进行更多测试。 - Jerry Dodge
这正是导致问题的原因。当它放置在一个纯FMX应用程序中时,这个表单完美地工作,但在这个容器内触发那些TChangeTabAction会导致一切冻结。 - Jerry Dodge
提出了新问题:http://stackoverflow.com/questions/36585316/fmx-form-in-vcl-app-via-tfiremonkeycontainer-application-freezing - Jerry Dodge
@JerryDodge 问题已经解决。请尝试在Github上使用最新版本。 - David

3

其实使用两种类型的表单并没有什么大不了的。但是请确保您在没有任何Owner的情况下实例化它们,因为Owner类型不兼容。

我刚刚创建了两个简单的测试项目,Project46和Project47。Project46包含了一个带有VCL表单的Unit25。Project47包含了一个带有FMX表单的Unit26。在Form25上,我添加了一个按钮,并设置了OnClick处理程序:

procedure TForm25.Button1Click(Sender: TObject);
var
  F: Unit26.TForm26;
begin
  F := TForm26.Create(nil);
  try
    F.ShowModal;
  finally
    F.Free;
  end;
end;

这个操作按预期进行了。但是表单应该严格独立于彼此。只有它们共同拥有的类型可以交换。


3

我自己没有尝试过,但是我知道一种已经确认的方法可以在同一个应用程序中混合使用 VCL 和 FireMonkey,它使用 RemObjects Hydra。还有一个未经证实的报告称,在 VCL 应用程序中可以使用 FireMonkey 表单,这来自于 Delphi Sorcery


1

下载并安装MonkeyMixer。加载您的VCL项目(或创建一个新项目),在项目资源管理器中右键单击它,然后您将看到“切换到FireMonkey”选项。点击该选项,您就可以将FireMonkey表单无缝添加到您的VCL项目中。如果您想要添加VCL表单/框架,则可以以同样的方式切换回VCL模式,只是菜单条目会显示“切换到VCL”。

享受吧!


0

FMX+VCL混合使用的所有问题都可以在WinAPI级别上解决。但是个人不建议您在实际应用中使用这种混合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接