Wednesday 17 July 2013

TFireMonkeyContainer - a VCL control for mixing VCL and FMX

I've created a small MPL-licensed component called TFireMonkeyContainer.  It's a VCL control that can host a FireMonkey form - 2D or 3D, it doesn't matter.

This will let you use FireMonkey's swishy graphics, animations, etc in an existing VCL application, either in a form among other controls, or if the host container is client-aligned then as though the whole window is a FireMonkey form (it just happens that the window chrome is a VCL form.)  As far as I know, while lots of people ask about mixing FireMonkey in a VCL app, there are no easy-to-use components which let you do so.  I hope, with some further development and bugfixes, this will do so.

Here's a screenshot from the example app:



How to use

  1. Drop a TFireMonkeyContainer control on a VCL form.
  2. Add a FMX form to your project if you haven't got one already (the IDE makes this difficult; you might need to create it in a separate FMX project and then add the unit to the VCL project.)
  3. At designtime, you can set the FireMonkeyForm property to an existing, auto-created FMX form. Note that for the IDE to see it, the form has to be open in a tab.
  4. At runtime, you can set the FireMonkeyForm property to a new instance of a FMX form.  Note that it doesn't take ownership of the form, so you will need to free the form yourself.  This is something that might change in future.

Known bugs

Yes, there definitely are known bugs.  This version is the result of only a couple of hours' work :)
  • The host form's title bar changes to paint as inactive when you click inside the hosted FMX form.  I plan to fix this by handling WM_NCACTIVATE and related messages; if you can think of a better way, by all means please let me know.
  • At designtime, you can't set the FireMonkeyForm property unless the FMX form is open in a tab in the IDE.
  • At designtime, the embedded FMX form draws a few pixels to the right and below where it should be.  You will see a border on the top and left sides of the controls.  I don't know why this is, and at runtime it is in the right place.
  • Designtime is fairly strange all around.  You can edit the hosted FMX control, such as by dragging a button around, but trying to do something like open a style editor causes lots of problems.  I'd recommend you regard it as view-only.

Possible future changes

This code is the result of one or two hours' work - it's early.  Please take that into account.  I thought it might be worth getting feedback on the component and see if it's useful before doing much more work.
That said, here are some possible future changes:
  • Make designtime view-only - don't let you edit the FMX form when it's displayed at designtime in the VCL editor, and just draw it there instead so you can see what it will look like.  This would probably make it a lot more stable.
  • Take ownership of the FMX form - set and forget.  (Currently, you have to delete the FMX form instance if you don't want a memory leak.)
  • Add two events for runtime form creation and deletion, so that when the component is created, you can handle an event and create a new FMX form, and when it is destroyed you can optionally do something with the FMX form before it is freed, or stop it being freed entirely.
I'm interested in other ideas too!

Credits

I saw some example code linked from this Delphi Sorcery post which inspired this component.  The code was DSharp.Windows.FMXAdapter.pas by Stefan Glienke.  My code is considerably expanded so I view it as a separate work - it solves some bugs (eg, removing flicker when the host VCL form is resized, hiding the phantom FMX application window, etc) and of course is a component.  Thanks go to those two pages for showing the basic technique!

Getting the code

You can grab the code via Subversion from Google Code here:
http://firemonkey-container.googlecode.com/svn/trunk/
or via the command line:
svn checkout http://firemonkey-container.googlecode.com/svn/trunk/ firemonkey-container-read-only

You will find two packages (one designtime, one runtime - both 32 and 64-bit) and one small example project.  It's only been tested with XE4 so far!

Have fun, and please contribute back any bugfixes you find.

3 comments:

  1. I recommend!
    I suggest only two changes:
    #1 on the FMXContainer.pas
    [ComponentPlatformsAttribute(pidWin32 or pidWin64)] //add this line
    TFireMonkeyContainer = class(TWinControl)
    #2 if don't have monkeymixer
    To have both types of forms (VCL, FMX) you must follow the following steps
    * Create the project
    * Edit the file manually dproj " VCL " to "None "

    ReplyDelete
    Replies
    1. Hi Edgar,

      I added #1, the attribute - see the latest source. Thanks for the suggestion!

      Re #2, do you have a link for MonkeyMixer? Simon's website seems to be down.

      Delete
  2. http://www.lakraven.com/downloads/MonkeyMixerSetup.exe

    ReplyDelete