0
votes

I'm using the TFireMonkeyContainer control to embed a Firemonkey form inside a VCL application. Initially, everything works fine. However, whenever I do something which triggers a TChangeTabAction (to slide back and forth between tabs in a TTabControl), the entire application freezes up and stops responding. Even Windows is unable to detect that it's not responding - the title bar is even frozen as well, and I have to either terminate the process from the IDE or from the Task Manager. The same form works perfectly when run purely in a Firemonkey application.

There's not much to it to reproduce the issue, no code at all, just form design.

  1. Install TFireMonkeyContainer control into IDE (or use dynamically)
  2. Create new VCL Forms Application
  3. Drop only one TFireMonkeyContainer control on VCL main form
  4. Create new FMX Form within same application
  5. Assign the FMX form to the Container
  6. In the FMX form, drop a TTabControl and add a few tabs
  7. In the FMX form, drop a new TActionList
  8. Add multiple TChangeTabActions into the Action List, one for each tab
  9. Assign each tab to one of the corresponding actions
  10. In the FMX form, drop a new button
  11. Assign one of the TChangeTabActions to the Button
  12. Run the application
  13. Note how when you move the mouse over the button, the UI responds well
  14. Note how you can switch between tabs manually with no problem
  15. Click the button on the FMX form
  16. Note how the UI no longer responds and the application seizes to continue

How can I make the FMX TChangeTabAction work as expected while embedding my form in this container?

EDIT

Just because the above explanation may not be enough for some, here's the form design of both forms:

VCL Form:

object frmVcl: TfrmVcl
  Left = 0
  Top = 0
  Caption = 'frmVcl'
  ClientHeight = 405
  ClientWidth = 666
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object FireMonkeyContainer1: TFireMonkeyContainer
    Left = 40
    Top = 40
    Width = 577
    Height = 305
    FireMonkeyForm = frmFiremonkey.Owner
  end
end

FMX Form:

object frmFiremonkey: TfrmFiremonkey
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object TabControl1: TTabControl
    Position.X = 24.000000000000000000
    Position.Y = 72.000000000000000000
    Size.Width = 585.000000000000000000
    Size.Height = 289.000000000000000000
    Size.PlatformDefault = False
    TabIndex = 0
    TabOrder = 0
    TabPosition = PlatformDefault
    object TabItem1: TTabItem
      CustomIcon = <
        item
        end>
      IsSelected = True
      Size.Width = 67.000000000000000000
      Size.Height = 26.000000000000000000
      Size.PlatformDefault = False
      StyleLookup = ''
      TabOrder = 0
      Text = 'TabItem1'
    end
    object TabItem2: TTabItem
      CustomIcon = <
        item
        end>
      IsSelected = False
      Size.Width = 68.000000000000000000
      Size.Height = 26.000000000000000000
      Size.PlatformDefault = False
      StyleLookup = ''
      TabOrder = 0
      Text = 'TabItem2'
    end
    object TabItem3: TTabItem
      CustomIcon = <
        item
        end>
      IsSelected = False
      Size.Width = 68.000000000000000000
      Size.Height = 26.000000000000000000
      Size.PlatformDefault = False
      StyleLookup = ''
      TabOrder = 0
      Text = 'TabItem3'
    end
  end
  object Button1: TButton
    Position.X = 32.000000000000000000
    Position.Y = 16.000000000000000000
    Size.Width = 105.000000000000000000
    Size.Height = 41.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 2
    Text = 'Button1'
    OnClick = Button1Click
  end
  object ActionList1: TActionList
    Left = 512
    Top = 24
    object ChangeTabAction1: TChangeTabAction
      Category = 'Tab'
      Tab = TabItem1
    end
    object ChangeTabAction2: TChangeTabAction
      Category = 'Tab'
      Tab = TabItem2
    end
    object ChangeTabAction3: TChangeTabAction
      Category = 'Tab'
      Tab = TabItem3
    end
  end
end
1
I'd like to know how this question "does not show any research effort", "is not clear" or "is not useful" as one downvoter seems to think?Jerry Dodge
Hi Jerry - author of TFireMonkeyContainer here. I'll look into it. Feel free to drop me a bug report / sample app at parnassus.co/support/file-bug-report too.David
@DavidM Done and done. It kinda sucks because the sliding effect is the whole reason why I designed my app in Firemonkey, yet for certain reasons the shell needs to stay VCL.Jerry Dodge

1 Answers

1
votes

TFireMonkeyContainer prevents the FMX application message loop from running, deferring to the VCL application message loop. The replacement Windows app service did nothing for the methods HandleMessage (and returned false) or WaitMessage, incorrectly assuming that since the FMX message loop never ran, they would never be called.

However, FMX's Application.ProcessMessages method can be manually called, of course, and that calls into the Windows app service methods, running a while loop, which ended instantly. The tab transition code calls ProcessMessages until the transition is complete, and since HandleMessage did nothing but also processed no messages, the transition never continued, causing an infinite loop while it waited until it was done.

The latest commit in Github fixes this, as well as fixes a couple of related app service methods to behave more like the default FMX application service.