使用canvas字段在自定义控件上绘制

时间:2017-02-17 09:14:27

标签: delphi

此代码生成错误:

调试器异常通知

项目Project3.exe引发异常类$ C0000005,并在0x7757e12c处发出消息'访问冲突:写入地址0x00000014'。

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

我通过删除pasteBmp.free找到了解决方案;从下面的代码行。似乎每次调用copyRect时,都会再次分配FOD_canvas字段的值。

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;

为什么会这样?我尝试使用谷歌搜索和Delphi帮助。

1 个答案:

答案 0 :(得分:2)

正如评论中所述,错误是因为您保留对已销毁的TCanvas的引用,然后尝试使用它进行绘制。您需要保留实际TBitmap的副本,然后在需要时可以使用它进行绘制:

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