通过TFireMonkeyContainer在VCL app中的FMX表单 - 应用程序冻结

时间:2016-04-12 22:36:52

标签: delphi firemonkey vcl delphi-10-seattle

我正在使用TFireMonkeyContainer控件将Firemonkey表单嵌入到VCL应用程序中。最初,一切正常。但是,每当我执行触发TChangeTabAction(在TTabControl中的选项卡之间来回滑动)的操作时,整个应用程序会冻结并停止响应。即使Windows无法检测到它没有响应 - 标题栏甚至也被冻结,我必须从IDE或任务管理器终止进程。纯粹在Firemonkey应用程序中运行时,相同的表单非常有效。

重现这个问题没有多少,根本没有代码,只是形式设计。

  1. TFireMonkeyContainer控件安装到IDE(或动态使用)
  2. 创建新的VCL表单应用程序
  3. 在VCL主表单上只删除一个TFireMonkeyContainer控件
  4. 在同一个应用程序中创建新的FMX表单
  5. 将FMX表单分配给Container
  6. 在FMX表单中,删除TTabControl并添加几个标签
  7. 在FMX表单中,删除新的TActionList
  8. 将多个TChangeTabAction添加到动作列表中,每个标签一个
  9. 将每个标签分配给其中一个相应的操作
  10. 在FMX表单中,删除一个新按钮
  11. 将其中一个TChangeTabAction分配给按钮
  12. 运行应用程序
  13. 请注意,当您将鼠标移到按钮上时,UI响应良好
  14. 请注意如何在没有问题的情况下手动切换选项卡
  15. 点击FMX表格上的按钮
  16. 请注意用户界面不再响应且应用程序抓住继续
  17. 在将此表单嵌入此容器时,如何使FMX TChangeTabAction按预期工作?

    修改

    仅仅因为上面的解释对某些人来说可能不够,这里是两种形式的表单设计:

    VCL表格:

    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表格:

    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 个答案:

答案 0 :(得分:1)

TFireMonkeyContainer阻止FMX应用程序消息循环运行,推迟到VCL应用程序消息循环。替换Windows应用程序服务对方法HandleMessage(并返回false)或WaitMessage没有任何作用,错误地假设由于FMX消息循环从未运行,因此永远不会调用它们。

然而,FMX的Application.ProcessMessages方法当然可以手动调用,并调用Windows应用服务方法,运行while循环,立即结束。选项卡转换代码调用ProcessMessages直到转换完成,并且由于HandleMessage什么也没做,但也没有处理任何消息,转换从未继续,导致无限循环,等待它完成。

latest commit in Github解决了这个问题,并修复了一些相关的应用服务方法,使其更像默认的FMX应用服务。