Delphi 绘图到FireMonkey TControl.Canvas输出到TForm Canvas
我刚刚开始将一个庞大的代码库转换为FireMonkey,但我遇到了一些困难 有一件事让我大吃一惊,那就是TControl.Canvas出现了一个大问题。如果调用不正确,则绘制到TCanvas,实际上绘制到窗体画布(具体来说,它在窗体上绘制为0,0,而不是自定义控件的客户端原点) 例如,在MouseMove事件中,我需要绘制一个选择。下面是一些示例代码:Delphi 绘图到FireMonkey TControl.Canvas输出到TForm Canvas,delphi,firemonkey,tcanvas,Delphi,Firemonkey,Tcanvas,我刚刚开始将一个庞大的代码库转换为FireMonkey,但我遇到了一些困难 有一件事让我大吃一惊,那就是TControl.Canvas出现了一个大问题。如果调用不正确,则绘制到TCanvas,实际上绘制到窗体画布(具体来说,它在窗体上绘制为0,0,而不是自定义控件的客户端原点) 例如,在MouseMove事件中,我需要绘制一个选择。下面是一些示例代码: procedure TMyCustomControl.MouseMove(Shift: TShiftState; sX, sY: Single)
procedure TMyCustomControl.MouseMove(Shift: TShiftState; sX, sY: Single);
begin
inherited;
...
Paint();
end;
procedure TMyCustomControl.Paint();
begin
PaintToCanvas(Canvas);
end;
在FireMonkey中使用此代码,可以对表单进行绘制(即表单上0,0处的输出)
如果我将MouseMove中的代码更改为Repaint();然后它正确地绘制到我的控制
显然,对于FMX,我需要触发控件的实际绘制(不仅仅是直接绘制),否则画布无效
我需要的是解释为什么它会这样工作。我的代码中有很多画布,所以我需要理解这一点,以便找出其他不兼容的代码
系统:Delphi 10.3 Rio、32或64位Windows应用程序。您不应该在重写的
Paint()之外直接绘制,甚至不应该在VCL中。如果某个操作需要重新绘制,则应该Invalidate()
或repaint()
控件,并让操作系统向控件发出信号,使其实际绘制()。这是对VCL和FMX的尝试。@Remy:我同意,但这主要是继承的代码,一直“正常工作”,所以我尽量不使用它。问题在于FMX画布不会以任何可预测的方式出现故障。如果canvas属性不是“有效”的,为什么不直接返回nil呢?这将使这些问题更容易发现。我可以添加一些防御性代码块,如:如果Canvas.BeginSceneCount=0,则引发Exception.create('Invalid Canvas');