Using canvas field to paint on a custom control

0

This code generates an error:


Debugger Exception Notification

Project Project3.exe raised exception class $C0000005 with message 'access violation at 0x7757e12c: write of address 0x00000014'.

if Fowner_draw then
   begin
   canvas.CopyRect(ClientRect, FOD_canvas, ClientRect);
   end

I found the solution by deleting pasteBmp.free; line from the code below. It seems like each time copyRect is called the value of FOD_canvas field is assigned again.

procedure Tncrtile.copy_rect(Cimage:timage; source:trect; dest:trect);
var
copyBmp,pasteBmp: TBitmap;
begin
if (Cimage.Picture.Graphic <> nil) and not Cimage.Picture.Graphic.Empty then
  begin
  copyBmp:=TBitmap.Create;
  pasteBmp:=TBitmap.Create;
    try
    copyBmp.Height:=Cimage.Height;
    copyBmp.Width:=Cimage.Width;
    pasteBmp.Height:=source.Height;
    pasteBmp.Width:=source.Width;
    copyBmp.canvas.Draw(0, 0, Cimage.Picture.Graphic);
    pasteBmp.Canvas.CopyRect(rect(0, 0, source.Width, source.Height), copyBmp.Canvas, source);
    FOD_canvas:=pasteBmp.Canvas;
    finally
    copyBmp.free;
    pasteBmp.free;
    end;
  Fdrawing_rect:=dest;
  Fowner_draw:=true;
  invalidate;
  end;
end;

Why is this happening? I tried googling and the Delphi help.

delphi
asked on Stack Overflow Feb 17, 2017 by Nasreddine Galfout • edited Jul 10, 2017 by Peter Mortensen

1 Answer

2

As stated in comments, the error is because you are keeping a reference to a destroyed TCanvas and then trying to draw with it. You need to keep a copy of the actual TBitmap instead and then you can draw with it when needed:

constructor Tncrtile.Create(AOwner: TComponent);
begin
  inherited;
  FOD_Bmp := TBitmap.Create;
end;

destructor Tncrtile.Destroy;
begin
  FOD_Bmp.Free;
  inherited;
end;

procedure Tncrtile.copy_rect(Cimage: TImage; Source, Dest: TRect);
var
  copyBmp, pasteBmp: TBitmap;
begin
  if (Cimage.Picture.Graphic <> nil) and (not Cimage.Picture.Graphic.Empty) then
  begin
    copyBmp := TBitmap.Create;
    pasteBmp := TBitmap.Create;
    try
      copyBmp.Height := Cimage.Height;
      copyBmp.Width := Cimage.Width;
      pasteBmp.Height := Source.Height;
      pasteBmp.Width := Source.Width;
      copyBmp.Canvas.Draw(0, 0, Cimage.Picture.Graphic);    
      pasteBmp.Canvas.CopyRect(Rect(0, 0, Source.Width, Source.Height), copyBmp.Canvas, Source);
      FOD_Bmp.Assign(pasteBmp);
    finally
      copyBmp.Free;
      pasteBmp.Free;
    end;
    Fdrawing_rect := Dest;
    Fowner_draw := True;
    Invalidate;
  end;
end;

...

if Fowner_draw and (not FOD_BMP.Empty) then
begin
  Canvas.CopyRect(ClientRect, FOD_Bmp.Canvas, ClientRect);
end
answered on Stack Overflow Feb 17, 2017 by Remy Lebeau

User contributions licensed under CC BY-SA 3.0