动态创建FMX窗体时BorderStyle设置导致的尺寸异常问题
解决FMX动态创建窗体时BorderStyle变更导致客户区尺寸异常的问题
问题分析
动态创建FMX窗体时,设置BorderStyle为Single或None后直接指定ClientWidth/ClientHeight,会出现尺寸计算异常:
- 即使明确设置客户区为300x300,窗体总尺寸仍保留
Sizeable样式对应的边框大小,导致实际客户区超出预期。 - 设计器内操作无此问题,VCL环境下变更边框样式会自动调整总尺寸以维持客户区固定,符合预期逻辑。
BorderStyle=None时直接设置Width/Height能临时解决,但Single样式因存在边框,此方法不适用。
解决方案
核心思路是触发FMX重新计算边框与客户区的尺寸关系,或手动推导正确的总窗体尺寸。
方法1:调用UpdateBounds强制刷新尺寸逻辑
设置BorderStyle和客户区尺寸后,调用UpdateBounds触发窗体重新计算尺寸,确保客户区大小符合设定:
var Form: TForm; Shape: TRectangle; begin // 修复Single样式的窗体 Form := TForm.CreateNew(Application); Form.BorderStyle := TFmxFormBorderStyle.Single; Form.Fill.Color := TAlphaColors.Yellow; Form.Fill.Kind := TBrushKind.Solid; Form.ClientWidth := 300; Form.ClientHeight := 300; // 强制同步边框与客户区尺寸计算 Form.UpdateBounds(Form.Left, Form.Top, Form.Width, Form.Height); Shape := TRectangle.Create(Form); Shape.Parent := Form; Shape.SetBounds(0, 0, 300, 300); Form.Show; // 修复None样式的窗体 Form := TForm.CreateNew(Application); Form.BorderStyle := TFmxFormBorderStyle.None; Form.Fill.Color := TAlphaColors.Yellow; Form.Fill.Kind := TBrushKind.Solid; Form.ClientWidth := 300; Form.ClientHeight := 300; Form.UpdateBounds(Form.Left, Form.Top, Form.Width, Form.Height); Shape := TRectangle.Create(Form); Shape.Parent := Form; Shape.SetBounds(0, 0, 300, 300); Form.Show; end;
方法2:手动计算Single样式的总窗体尺寸
针对Single样式,直接通过边框、标题栏参数反推总尺寸,确保客户区为设定值:
var Form: TForm; Shape: TRectangle; BorderWidth: Integer; CaptionHeight: Integer; begin Form := TForm.CreateNew(Application); Form.BorderStyle := TFmxFormBorderStyle.Single; Form.Fill.Color := TAlphaColors.Yellow; Form.Fill.Kind := TBrushKind.Solid; // 获取Single样式的边框与标题栏尺寸 BorderWidth := Form.BorderWidth; CaptionHeight := Form.CaptionHeight; // 计算总尺寸:客户区尺寸 + 左右边框*2 + 标题栏高度 + 底部边框 Form.Width := 300 + BorderWidth * 2; Form.Height := 300 + CaptionHeight + BorderWidth; Shape := TRectangle.Create(Form); Shape.Parent := Form; Shape.SetBounds(0, 0, 300, 300); Form.Show; end;
方法3:先显示窗体再修改样式(临时方案)
先以默认Sizeable样式创建并显示窗体,再修改BorderStyle和客户区尺寸,此时FMX会正确计算尺寸关系:
var Form: TForm; Shape: TRectangle; begin Form := TForm.CreateNew(Application); Form.BorderStyle := TFmxFormBorderStyle.Sizeable; Form.Fill.Color := TAlphaColors.Yellow; Form.Fill.Kind := TBrushKind.Solid; Form.ClientWidth := 300; Form.ClientHeight := 300; Form.Show; // 显示后修改边框样式并重置客户区尺寸 Form.BorderStyle := TFmxFormBorderStyle.Single; Form.ClientWidth := 300; Form.ClientHeight := 300; Shape := TRectangle.Create(Form); Shape.Parent := Form; Shape.SetBounds(0, 0, 300, 300); end;
原理说明
FMX动态创建流程中,BorderStyle变更不会自动触发尺寸重新计算,而设计器会在样式变更时同步调整尺寸逻辑。调用UpdateBounds可强制窗体重新解析当前边框样式下的客户区与总尺寸关系;手动计算则是绕过FMX的异常逻辑,直接基于系统边框参数推导正确值。
内容的提问来源于stack exchange,提问作者Digão Dalpiaz
相关产品推荐
相关产品推荐

