通过 TFireMonkeyContainer 在 VCL 应用程序中形成 FMX - 应用程序冻结
FMX form in VCL app via TFireMonkeyContainer - application freezing
我正在使用 TFireMonkeyContainer
控件在 VCL 应用程序中嵌入 Firemonkey 表单。最初,一切正常。但是,每当我执行触发 TChangeTabAction
的操作(在 TTabControl
中的选项卡之间来回滑动)时,整个应用程序都会冻结并停止响应。即使 Windows 也无法检测到它没有响应 - 标题栏甚至也被冻结,我必须从 IDE 或任务管理器中终止进程。当 运行 完全在 Firemonkey 应用程序中时,相同的表单可以完美工作。
重现问题并不多,根本没有代码,只是表单设计。
- 将
TFireMonkeyContainer
控件安装到 IDE(或动态使用)
- 创建新的 VCL 表单应用程序
- 在 VCL 主窗体上只删除一个
TFireMonkeyContainer
控件
- 在同一应用程序中创建新的 FMX 表单
- 将 FMX 表单分配给容器
- 在 FMX 表单中,删除一个
TTabControl
并添加几个选项卡
- 在 FMX 表单中,放置一个新的
TActionList
- 将多个
TChangeTabAction
添加到操作列表中,每个选项卡一个
- 将每个选项卡分配给相应的操作之一
- 在 FMX 表单中,放置一个新按钮
- 将
TChangeTabAction
之一分配给按钮
- 运行 申请
- 请注意当您将鼠标移到按钮上时,UI 响应良好
- 请注意如何在选项卡之间手动切换而不会出现问题
- 单击 FMX 表单上的按钮
- 请注意 UI 如何不再响应并且应用程序会占用以继续
如何使 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
TFireMonkeyContainer
阻止 FMX 应用程序消息循环 运行,推迟到 VCL 应用程序消息循环。替换 Windows 应用服务对方法 HandleMessage
(并返回 false)或 WaitMessage
没有做任何事情,错误地假设因为 FMX 消息循环从不 运行,它们永远不会打电话。
但是FMX的Application.ProcessMessages
方法当然可以手动调用,调用到Windows应用服务方法,运行一个while循环,瞬间结束。选项卡 t运行sition 代码调用 ProcessMessages
直到 t运行sition 完成,并且由于 HandleMessage
什么也没做,也没有处理任何消息,因此 t运行 sition 从未继续,导致无限循环等待直到它完成。
latest commit in Github 修复了这个问题,并修复了一些相关的应用服务方法,使其表现得更像默认的 FMX 应用服务。
我正在使用 TFireMonkeyContainer
控件在 VCL 应用程序中嵌入 Firemonkey 表单。最初,一切正常。但是,每当我执行触发 TChangeTabAction
的操作(在 TTabControl
中的选项卡之间来回滑动)时,整个应用程序都会冻结并停止响应。即使 Windows 也无法检测到它没有响应 - 标题栏甚至也被冻结,我必须从 IDE 或任务管理器中终止进程。当 运行 完全在 Firemonkey 应用程序中时,相同的表单可以完美工作。
重现问题并不多,根本没有代码,只是表单设计。
- 将
TFireMonkeyContainer
控件安装到 IDE(或动态使用) - 创建新的 VCL 表单应用程序
- 在 VCL 主窗体上只删除一个
TFireMonkeyContainer
控件 - 在同一应用程序中创建新的 FMX 表单
- 将 FMX 表单分配给容器
- 在 FMX 表单中,删除一个
TTabControl
并添加几个选项卡 - 在 FMX 表单中,放置一个新的
TActionList
- 将多个
TChangeTabAction
添加到操作列表中,每个选项卡一个 - 将每个选项卡分配给相应的操作之一
- 在 FMX 表单中,放置一个新按钮
- 将
TChangeTabAction
之一分配给按钮 - 运行 申请
- 请注意当您将鼠标移到按钮上时,UI 响应良好
- 请注意如何在选项卡之间手动切换而不会出现问题
- 单击 FMX 表单上的按钮
- 请注意 UI 如何不再响应并且应用程序会占用以继续
如何使 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
TFireMonkeyContainer
阻止 FMX 应用程序消息循环 运行,推迟到 VCL 应用程序消息循环。替换 Windows 应用服务对方法 HandleMessage
(并返回 false)或 WaitMessage
没有做任何事情,错误地假设因为 FMX 消息循环从不 运行,它们永远不会打电话。
但是FMX的Application.ProcessMessages
方法当然可以手动调用,调用到Windows应用服务方法,运行一个while循环,瞬间结束。选项卡 t运行sition 代码调用 ProcessMessages
直到 t运行sition 完成,并且由于 HandleMessage
什么也没做,也没有处理任何消息,因此 t运行 sition 从未继续,导致无限循环等待直到它完成。
latest commit in Github 修复了这个问题,并修复了一些相关的应用服务方法,使其表现得更像默认的 FMX 应用服务。