The example application showing a 3D FireMonkey form. On the other tab is a standard 2D form. |
On Wednesday I announced TFireMonkeyContainer, a VCL control that can host a FireMonkey form, allowing you to mix FireMonkey elements into your VCL app. It was (and is) a new project, and the announcement page listed several known bugs and possible future design changes.
Bugs: gone! Design changes: made! The current state is not quite perfect but is bug-free enough I feel happy about you using it in real applications, or at least trying it out. (With the caveat that I’m the only one who has tested it so far, and my entire QA department is me :) If you try it, please let me know how it goes.
Bugs fixed
- Focus now correctly follows the host VCL and hosted FMX forms
- Window activation now correctly follows the host VCL and hosted FMX forms, when switching by clicking on the host VCL form, the hosted FMX form, via alt-tab, via the taskbar, and when there are several VCL forms and several hosted FMX forms in the one application.
- The title bar of host VCL forms correctly changes when the form is active and inactive.
- An exception is now thrown when two containers both try to host the same form.
Design changes
This FireMonkey form embedded in the VCL form can’t be edited in the VCL designer – it’s a static preview. Switch to the FMX form tab to edit it. |
- Design-time (in the IDE): When a FireMonkey form is hosted in a VCL form in designtime, it shows an uneditable view of the hosted form. (This used to be an editable FireMonkey form, ie you could invoke the FireMonkey designer. This only partially worked and caused a lot of problems.) Switch tabs to the FireMonkey form’s IDE design tab to edit the FireMonkey form. Changes will be reflected immediately when you switch back to the VCL form’s design tab.
- There are two new events you can use to control hosting the FireMonkey form. This means there are three ways to embed a FireMonkey form:
- Set the FireMonkeyForm property at design-time. (Not recommended, see ‘Known problems’ below.)
- Set the FireMonkeyForm property at runtime.
- Use the OnCreateFMXForm and OnDestroyFMXForm events.
- OnCreateFMXForm fires when the component is first created. It has a var Form parameter which you can use to set the hosted FireMonkey form. If a form was specified at designtime, Form refers to it. If you change it, OnDestroyFMXForm will be called for the old value.
- OnDestroyFMXForm fires when the component is destroyed. Much like a TForm‘s OnClose event, you can choose an action to apply to the hosted FMX form, eg to free it. The default is to do nothing, since it was probably created with an owner. The Destroy event also occurs when you change the Form parameter in the Create event (eg, when there was a FMX form set at design-time, but in the Create event you change it to another form.)
Known problems
- When you set the FireMonkeyForm property at designtime, you can only set it to a FMX form that is open in a tab in the IDE – otherwise the IDE doesn’t see it and won’t show it in the dropdown in the Object Inspector. When the IDE tab is closed, the reference is invalid – and this means the FireMonkeyForm property is cleared. This might be due to problems mixing VCL and FMX forms in the one app, or (more likely) it might be due to a mistake I’ve made in how to correctly reference another form in a component. Suggested workaround: set the property at runtime, or use the OnCreateFMXForm and OnDestroyFMXForm events instead.
Notes, and getting the code
The component subclasses both the VCL form and the FMX form in order to catch the WM_NCACTIVATE (VCL form) and WM_ACTIVATE and WM_MOUSEACTIVATE (FMX form) messages. I’m not an expert in window activation and there may be bugs (or I might have just plain written bad code) in the handlers. I’m also not certain I have hit on completely the right design for the events. I’d quite appreciate feedback if you use the component and feel that the events that occur are a bad design or force you to write ugly code. The same goes for any aspects of the component, really.
You can download the latest version from the Google code homepage and Subversion source checkout.