FireMonkey中如何捕获包含TText的TLayout为Bitmap?
解决FireMonkey中TLayout捕获TText控件的问题
在RAD Studio 12的FireMonkey项目中,直接使用TLayout.PaintTo或MakeScreenshot无法捕获TText控件的原因是:TText属于轻量级的TGraphicControl子类,这类控件的绘制逻辑与TLabel(TControl子类)不同,默认的PaintTo方法不会自动触发其绘制流程。以下是两种可行的解决方法:
方法一:使用RenderToBitmap方法(推荐)
FireMonkey从RAD Studio 10.4开始提供了TControl.RenderToBitmap方法,专门用于将控件及其所有层级的子控件完整渲染到位图中,能完美处理TText这类轻量级控件。
C++代码示例:
#include <FMX.Controls.hpp> #include <FMX.Graphics.hpp> TBitmap* CaptureFullLayout(TLayout* TargetLayout) { if (!TargetLayout || !TargetLayout->Visible) return nullptr; TBitmap* ResultBmp = new TBitmap(); try { // 设置位图尺寸与布局一致 ResultBmp->SetSize(TargetLayout->Width, TargetLayout->Height); // 渲染布局及其所有子控件到位图 TargetLayout->RenderToBitmap( ResultBmp, TargetLayout->BoundsRect, // 源区域(布局自身范围) TRectF(0, 0, TargetLayout->Width, TargetLayout->Height) // 目标区域(位图范围) ); return ResultBmp; } catch (...) { delete ResultBmp; throw; } }
使用时直接调用该函数,获取返回的TBitmap后即可保存或使用,记得使用完后手动释放内存。
方法二:手动递归绘制所有控件
如果需要兼容旧版本(或自定义绘制逻辑),可以手动遍历布局的所有子控件,逐个调用PaintTo方法,确保所有层级的控件都被绘制。
C++代码示例:
#include <FMX.Controls.hpp> #include <FMX.Graphics.hpp> void PaintControlHierarchy(TControl* Control, TBitmap* DestBmp, const TRectF& DestRect) { if (!Control || !Control->Visible || !DestBmp) return; // 绘制当前控件 Control->PaintTo(DestBmp->Canvas, DestRect); // 递归绘制所有子控件 for (int i = 0; i < Control->ChildrenCount; ++i) { TControl* ChildCtrl = static_cast<TControl*>(Control->Children[i]); TRectF ChildSrc = ChildCtrl->BoundsRect; // 计算子控件在目标位图中的位置 TRectF ChildDest( DestRect.Left + ChildSrc.Left, DestRect.Top + ChildSrc.Top, DestRect.Left + ChildSrc.Right, DestRect.Top + ChildSrc.Bottom ); PaintControlHierarchy(ChildCtrl, DestBmp, ChildDest); } } TBitmap* CaptureLayoutManual(TLayout* TargetLayout) { if (!TargetLayout || !TargetLayout->Visible) return nullptr; TBitmap* ResultBmp = new TBitmap(); ResultBmp->SetSize(TargetLayout->Width, TargetLayout->Height); PaintControlHierarchy(TargetLayout, ResultBmp, TRectF(0, 0, TargetLayout->Width, TargetLayout->Height)); return ResultBmp; }
额外注意事项
- 确保TText控件的
Visible属性为true,Opacity为1,且没有被其他控件完全遮挡; - 如果需要捕获整个窗体,直接将上述代码中的
TLayout替换为TForm即可,逻辑完全通用; - 使用完TBitmap后务必调用
delete释放内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Barry Andrews
相关产品推荐
相关产品推荐

