Friday, September 2, 2011

Delphi XE2 - heating up the hype: playing the matchmaker for VCL and FMX

To be honest, FireMonkey did not interest me much because of the fact that it is not compatible with any VCL application - says the documentation - actually that's not the truth!

To keep the long story short: You can have both in one! (Disclaimer: I did only a few tests and it worked all fine - actually I have no clue if somewhere it's incompatible but I leave that as an exercise to you).

Just create a new FireMonkey form (2D or 3D, doesn't matter) save it and then add it to your VCL application (just accept the warning). You can create your FMX form instance somewhere and just show it - no problem. But what if you want to create some nice control with animations or something and embed it into your existing VCL form? Well, put a TPanel on your VCL form and include the brandnew unit DSharp.Windows.FMXAdapter.pas after the Vcl.ExtCtrls. Then just create your FMX form somewhere and assign it to the new Form property of your Panel - and boom, there you go.

As I said, I just came up with this and it's mostly untested - but that's the case for FireMonkey anyway, isn't it? So I thought this may be very interesting for a few people - especially those that used VGScene before. So have fun creating your shiny and new FMX forms and use them in your existing VCL apps. ;)

13 comments:

  1. Russian Roulette is a fun game to play.

    "I but a bullet in this gun put it to my head and pulled the trigger a few times and it seemed OK to me... clearly the people that make guns and ammunition don't know what they are talking about when they say they can be dangerous!"

    ;)

    ReplyDelete
  2. With DUnit-Tests Russian Roulette is also a safe game as you can see here:

    http://www.youtube.com/watch?v=3ZzoB6xBWOI&feature=player_embedded

    ReplyDelete
  3. I'm so sorry Jolyon, that I could not make some extensive testing for something that came out like 2 days ago...

    Anyway since VCL and FMX are two separate frameworks I expect them to work together. FMX form is just a regular window that I can put whereever I want. You only have to be careful with your uses clauses and fully qualify the units to avoid ambiguity when you have both in your application.

    ReplyDelete
  4. Nice find Stefan. I'll be giving this a spin.

    ReplyDelete
  5. Stefan, I wasn't criticising your testing regime. No amount of testing can prove that it is safe to mix FireMonkey and VCL.

    It isn't a question of there being a deliberate design constraint to prevent it, thus if you can work around that constraint you have somehow proven something. Rather it is simply that no consideration for co-existence of FM in a VCL app (or vice versa) has been given in *either* framework.

    Thus, you can prove that scenarion "A" works by building it and seeing that it works. But this tells you nothing about the viability of scenario "B" (in fact, it doesn't necessarily tell you enough about scenario "A" either as the instability may be in the form of a Heisenbug that simply hasn't yet manifested itself in that scenario either).

    The principle problem is that the message dispatch mechanism in FireMonkey is very, very different from the mechanism in the VCL. And neither mechanism expects any *other* framework to be "listening in" on that message queue.

    Until I've seen the source of the FireMonkey framework I can't say what conflicts might arise, but it's enough for me that Embarcadero have said "we don't guarantee this will work". I might find that it does work only to find myself high and dry after months of development when I finally run across a scenario that renders my application useless.


    Someone might then ask how RemObjects are able to offer/claim the ability to mix FM and VCL code in Hydra...

    I would ask this in return... if it's so easy, why do they feel it's such a big deal to make it worth making a part of Hydra ?

    (and I'd also suggest that if you really have to do this, then at least shore up your applications future security with the peace of mind you will get from being able to get support from RemObjects for any failings that you might uncover... they presumably won't get much help from Embarcadero if the problem is a deep, deep conflict between the frameworks, but at least you will have the resources of RemObjects looking into it for you, rather than flailing around entirely on your own)

    ReplyDelete
  6. You know that FireMonkey is based on various technologies (VGScene, DXScene, GLScene) that all worked with the VCL, right?

    So I rather think the guys at Embarcadero just did not want that compatibility hell for FireMonkey right from the start so they don't support it officially although there is no reason why it should not work together. Maybe we will know since I asked that on the official forums - still waiting for some answer.

    Anyway I don't claim this is the only working solution and there is no better, if I had it I would sell it before RemObjects does.

    I just tried to provide something for those coming from VGScene or wanting to put a nice animation made with FireMonkey into their VCL application. It's up to them to test it, use it, provide feedback or ignore it.

    Btw, check your sources (http://blogs.remobjects.com/blogs/ejay/2011/08/18/p2909): Hydra is not only about mixing FireMonkey and VCL but mixing FireMonkey/WinForms and WPF/FireMonkey

    ReplyDelete
  7. Great tip, Stefan!

    I tried the other way around - to show a **standalone* VCL form in a FMX application successfully, however, I failed to find a way embedding a VCL form into a FMX panel or a FMX form in a FMX application. Any hints?

    The code I tried:

    frmVcl := TFrmMyVcl.Create(self);
    frmVcl.ParentWindow := self.Handle;
    frmVcl.Show;

    ReplyDelete
  8. @Edwin: Actually I think that's not that easy (if possible at all) because as far as I have seen in FireMonkey only the window itself has a window handle. Even if you can make your VCL window child of the FMX window that doesn't do anything because FMX does not work that way.

    Maybe THAT's a task for the RemObjects guys.

    ReplyDelete
  9. @Stefan,

    But a FMX formis still a win32/win64 window on the MS Windows platform, right? So can we make it a parent window of other windows? (I don't know much about windows API.) If yes, we can set the bounds of the child windows in a timer.

    ReplyDelete
  10. @Edwin: Yes, I think you can do that using the Winapi.Windows.SetParent routine instead of using the property (which results in a recreation of the handle and therefor might not work). Anyway the FMX form did not show anything for me but I got it flashing when doing the Show() which indicates that something happened. I have not enough knowledge of FMX (yet) to tell what is necessary to make it work as a host for some VCL element.

    ReplyDelete
  11. @Stefan, yes, I failed too...

    The Hydra costs $499.

    ReplyDelete
  12. Looks promising, thanks for the unit!

    I’ve encountered one caveat, though: don’t set the Transparent property of the form to True; that disabled Aero on my Win7 machine (had to reboot to get it back enabled).

    Also, after setting Transparent back to False, the FMXForm got instantiated twice; once inside the VCL form, and once stand-alone. I had to manually remove the Transparent property from the .fmx resource file to get it working properly again.

    ReplyDelete
  13. Just discovered this - its a lifesaver and works well! Thanks.

    BUT it only seems to work if the form is a standalone form (e.g. the main form) within the application. I have an application with a number of child forms, which are embedded in the main form, setting the parent of the child form to a panel within the main form. If I then try to embed an FMX form within the child form, it fails to display (although it shows now errors). The same child form, if set as the application main form, displays the FMX form correctly.

    Is there any workaround that will allow me to do this?

    ReplyDelete