4

我正在尝试为TDBGridEh. 问题是当我更改钢笔、画笔的属性时……绘画变得凌乱。那是因为控件在调用事件处理程序后自己做了一些额外的绘制。所以我必须保留所有道具,然后在我自己的画完成时重新设置它们。

我尝试创建自己的TControlCanvas网格并将其分配给它,但我得到一个运行时异常消息:

无法将 TControlCanvas 分配给 TControlCanvas

,这表明该AssignTo方法既不是为其祖先实现的,TControlCanvas也不是为其祖先实现的。所以我的问题是:

  1. 为什么TControlCanvas没有AssignTo方法?问题是什么?

  2. 如何保留和恢复 TControlCanvas 的所有属性?我的意思是比创建TPen, TBrush,TFont等更方便的东西。

4

2 回答 2

6

虽然TCanvas实际上并没有封装这些 API 函数,但可以使用SaveDCRestoreDC执行您需要的操作。来自 MSDN:

SaveDC函数通过将描述选定对象和图形模式(例如位图、画笔、调色板、字体、笔、区域、绘图模式和映射模式)的数据复制到上下文来保存指定设备上下文 (DC) 的当前状态堆。

[...]

RestoreDC函数将设备上下文 (DC) 恢复到指定状态。通过从先前调用 SaveDC 函数创建的堆栈中弹出状态信息来恢复 DC。

一个可能的代码示例:

uses
  Winapi.Windows;
...
var
  SavedDC: Integer;
begin
  SavedDC := SaveDC(Canvas.Handle);
  try
   // Painting code
  finally
    RestoreDC(Canvas.Handle, SavedDC);
  end;
end;

编辑:
我意识到仅此一项可能不是答案。这将处理由Delphi VCL 端的TCanvas/对象表示的 Windows 端的设备上下文。TControlCanvas但它不会改变 VCL 持有的任何TFontTBrushTPen对象。从测试来看,例如每当 Delphi 使用 Canvas 的Brush.GetHandle( FillRect, FrameRect) 时,它仍然是更改后的 Brush。

所以最好的选择是使用SaveDCRestoreDC结合存储和恢复,Pen就像Uwe Raabe 的回答一样。FontBrush

于 2018-03-27T08:14:19.157 回答
5

不确定这是否符合您的期望,但有TPenRecall,TBrushRecallTFontRecall以半自动方式保存和恢复这三个属性的设置。

处理非常简单:使用相应的属性作为参数创建这些类的实例,然后使用PenBrushFont做任何你想做的事情。最后释放这些实例,这将恢复设置。

结合一个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;

用法:

procedure TForm274.DoYourDrawing(ACanvas: TCanvas);
begin
  TCanvasSaver.SaveCanvas(ACanvas);
  { Change Pen, Brush and Font of ACanvas and do whatever you need to do.
    Make sure that ACanvas is still valid and the same instance as at the entry of this method. }
end;
于 2018-03-27T08:10:36.643 回答