Search code examples
delphigraphicstcanvas

How can I keep all properties of a TControlCanvas and restore them later?


I'm trying to write a custom draw cell method for a TDBGridEh. The problem is when I change properties of pen, brush, ... the painting becomes messy. That's because the control does some extra painting itself after it calls the event handler. So I have to keep all props and then reset them when my own painting was finished.

I tried to create my own TControlCanvas and assign grid's one to it, but I get a run-time exception with message:

Cannot assign a TControlCanvas to a TControlCanvas

, that indicates the AssignTo method is not implemented for TControlCanvas nor for its ancestors. So my questions are:

  1. Why TControlCanvas does not have an AssignTo method? What is the problem?

  2. How can I keep and restore all properties of a TControlCanvas? And by that I mean something more convenient than creating TPen, TBrush, TFont, etc. .


Solution

  • Not sure if this fits what your expects, but there are TPenRecall, TBrushRecall and TFontRecall to save and restore the settings of these three properties in a semi-automatic way.

    The handling is pretty simple: Create an instance of these classes with the corresponding properties as the parameter and do whatever you want with Pen, Brush and Font. In the end free those instances, which will restore the settings.

    In combination with a TObjectList and some internal reference counting the effort needed to save and restore these canvas properties can be reduced to a one liner.

    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;
    

    Usage:

    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;