Delphi 如何保留TControlCanvas的所有属性并在以后恢复它们?
我正在尝试编写一个自定义的绘制单元格方法。问题是,当我更改笔、画笔等的属性时。。。这幅画变得凌乱不堪。这是因为控件在调用事件处理程序后会自己进行一些额外的绘制。所以我必须保留所有道具,然后在我自己的画完成后重置它们 我试图创建我自己的Delphi 如何保留TControlCanvas的所有属性并在以后恢复它们?,delphi,graphics,tcanvas,Delphi,Graphics,Tcanvas,我正在尝试编写一个自定义的绘制单元格方法。问题是,当我更改笔、画笔等的属性时。。。这幅画变得凌乱不堪。这是因为控件在调用事件处理程序后会自己进行一些额外的绘制。所以我必须保留所有道具,然后在我自己的画完成后重置它们 我试图创建我自己的TControlCanvas并将网格的一个分配给它,但我得到一个运行时异常消息: 无法将TControlCanvas分配给TControlCanvas ,表示未为TControlCanvas或其祖先实现AssignTo方法。因此,我的问题是: 为什么TControl
TControlCanvas
并将网格的一个分配给它,但我得到一个运行时异常消息:
无法将TControlCanvas分配给TControlCanvas
,表示未为TControlCanvas
或其祖先实现AssignTo
方法。因此,我的问题是:
TControlCanvas
没有AssignTo
方法?有什么问题TPen
,TBrush
,TFont
等更方便的东西不确定这是否符合您的期望,但有
TPenRecall
、TBrushRecall
和tfontecall
以半自动方式保存和恢复这三个属性的设置
处理非常简单:创建这些类的一个实例,并将相应的属性作为参数,然后使用Pen、Brush和Font执行任何操作。最后释放这些实例,这将恢复设置
结合TObjectList
和一些内部引用,保存和恢复这些画布属性所需的工作量可以减少到一行
type
TCanvasSaver = class(TInterfacedObject)
private
FStorage: TObjectList<TRecall>;
public
constructor Create(ACanvas: TCanvas);
destructor Destroy; override;
class function SaveCanvas(ACanvas: TCanvas): IInterface;
end;
constructor TCanvasSaver.Create(ACanvas: TCanvas);
begin
inherited Create;
FStorage := TObjectList<TRecall>.Create(True);
FStorage.Add(TFontRecall.Create(ACanvas.Font));
FStorage.Add(TBrushRecall.Create(ACanvas.Brush));
FStorage.Add(TPenRecall.Create(ACanvas.Pen));
end;
destructor TCanvasSaver.Destroy;
begin
FStorage.Free;
inherited;
end;
class function TCanvasSaver.SaveCanvas(ACanvas: TCanvas): IInterface;
begin
Result := Self.Create(ACanvas);
end;
虽然
TCanvas
实际上并没有封装这些API函数,但可以使用SaveDC
和RestoreDC
来执行您需要的操作。从MSDN:
该函数通过复制描述选定对象和对象的数据来保存指定设备上下文(DC)的当前状态
图形模式(如位图、画笔、调色板、字体、笔、区域、,
绘制模式和映射模式)到上下文堆栈
[……]
此函数用于将设备上下文(DC)恢复到
指定状态。通过弹出状态信息来恢复DC
由先前对SaveDC函数的调用创建的堆栈
可能的代码示例:
uses
Winapi.Windows;
...
var
SavedDC: Integer;
begin
SavedDC := SaveDC(Canvas.Handle);
try
// Painting code
finally
RestoreDC(Canvas.Handle, SavedDC);
end;
end;
编辑:我意识到单凭这一点可能无法解决问题。这将处理Windows端的设备上下文,该上下文由Delphi的VCL端的
TCanvas
/TControlCanvas
对象表示。
但它不会改变VCL持有的任何TFont
、TBrush
或TPen
对象。从测试来看,它看起来是这样的,例如,每当Delphi使用画布的画笔.GetHandle
(FillRect
,FrameRect
)时,它仍然是更改过的画笔
因此,最好的办法是将
SaveDC
和RestoreDC
与存储和恢复Pen
、Font
和Brush
结合使用,就像Uwe Raabe的回答一样 在Graphics.pas
和SaveDC
/RestoreDC
中,在Windows.pas
中有TFontRecall
及其同级。Tnx,它解决了所有刷子问题。但是我的钢笔还是有一些问题。最后,我使用了TRecall
substands.Hm,您在绘制时是否仍在创建一个新的临时TControlCanvas
?调用Canvas.Refresh时笔问题是否消失代码>在RestoreDC
之后?是<代码>刷新
修复了它。问题是什么?@saa是一篇试图解释刷新的文章。虽然我对用法和解释都不太确信,tcavassaver.Create(ACanvas)代码>因电弧而产生的线路工作?在D2007中,不调用析构函数。而且,是继承的构造函数中的代码>行没有编译-它必须是Create继承的代码>在D2007中。@UliGerhardt,谢谢你的提示!似乎我的剪贴板上有一个过时的代码版本。TCanvasSaver.SaveCanvas返回一个接口,该接口隐式保持,直到方法结束。
uses
Winapi.Windows;
...
var
SavedDC: Integer;
begin
SavedDC := SaveDC(Canvas.Handle);
try
// Painting code
finally
RestoreDC(Canvas.Handle, SavedDC);
end;
end;