View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0021981LazarusLCLpublic2012-05-08 00:362012-06-06 11:41
ReporterLeonardo M. Ramé 
Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
StatusnewResolutionopen 
PlatformOSOS Version
Product Version1.1 (SVN)Product Build 
Target VersionFixed in Version 
Summary0021981: TBitmap.CopyRect from TPaintbox.canvas bug
DescriptionWhen doing a TBitmap.CopyRect from a TPaintBox's canvas, the bitmap is filled with all the content inside AND over the PaintBox surface. I should only copy the content's of the paintbox:

Here's an example:

var
  lBmp: TBitmap;
begin
  lBmp := TBitmap.Create;
  lBmp.Width := PaintBox1.Width;
  lBmp.Height := PaintBox1.Height;
  try
    lBmp.Canvas.CopyRect(
      Rect(0, 0, lBmp.Width, lBmp.Height),
      PaintBox1.Canvas,
      Rect(0, 0, lBmp.Width, lBmp.Height)
    );
    Clipboard.Assign(lBmp);
  finally
    lBmp.Free;
  end;

I also attached a testing program.
TagsNo tags attached.
Fixed in Revision
LazTarget
Widgetset
Attached Filesgz file icon test.tar.gz [^] (1,767 bytes) 2012-05-08 00:36

- Relationships
related to 0020642closedZeljan Rikalo TPaintBox.Canvas is Larger than TPaintBox. 
related to 0022163new Canvas size out-of-sync 

-  Notes
(0059375)
Avishai (reporter)
2012-05-08 02:18

TPaintBox.Canvas is normally larger that TPaintBox. TPaintBox.Canvas seems to be as large as whatever it's parent is. For a workaround until it is fixed, use the TPaintBox.Height/Width, not the TPaintBox.CANVAS.Height/Width. Or you can put TPaintBox.Align:= alClient on a TPanel. Then the Canvas will match the TPainBox size.
(0059377)
Zeljan Rikalo (developer)
2012-05-08 07:47

Yes, it's known problem (bug ? ) with canvas size (w/h).
(0059389)
Leonardo M. Ramé (reporter)
2012-05-08 13:05

Avishal, I tested your suggestion, and it didn't work, I also used fixed values but it also didn't work.

Here's what I did:

procedure TForm1.Button1Click(Sender: TObject);
var
  lBmp: TBitmap;
begin
  lBmp := TBitmap.Create;
  lBmp.Width := 200;
  lBmp.Height := 200;
  try
    lBmp.Canvas.CopyRect(
      Rect(0, 0, 200, 200),
      PaintBox1.Canvas,
      Rect(0, 0, 200, 200)
    );
    Clipboard.Assign(lBmp);
  finally
    lBmp.Free;
  end;
end;
(0059390)
Avishai (reporter)
2012-05-08 13:50

I tested your (second) code and it worked for me on Win7. But I found a new problem. If something is in front of TPaintBox, it is also copied to clipboard. Bug, or Feature???
(0059392)
Leonardo M. Ramé (reporter)
2012-05-08 14:03

> if something is in front of TPaintBox, it is also copied to clipboard

That's why I registered this as a bug. In my example, I placed a TButton over the PaintBox, when I do CopyRect, the button is also included in the copy.
(0059393)
Avishai (reporter)
2012-05-08 14:15
edited on: 2012-05-08 14:18

Yes. That isn't what I expected either. I will try TImage to see if it is the same.

UpDate: TImage worked for me in a more expected way. I got exactly what I wanted.

(0059394)
Leonardo M. Ramé (reporter)
2012-05-08 14:25

Sadly I can't use TImage. Hopefully this bug can be fixed.
(0059395)
Avishai (reporter)
2012-05-08 14:31

Just a thought. Can you change TButton.Visible:= False while you make the Copy?
(0059396)
Mattias Gaertner (manager)
2012-05-08 14:48

About TPainBox.Canvas size:
TPainBox is not a TWinControl and therefore uses the Handle of its Parent. So the Canvas is the Canvas of its Parent. During OnPaint origin is moved and clipping added. Clipping does not change the Canvas.Width/Height.
This is by design.
(0059398)
Mattias Gaertner (manager)
2012-05-08 14:58

In other words:
If you want to access the TPaintBox.Canvas outside its OnPaint event you have to move the origin and apply clipping yourself.

Or use a TWinControl like TImage.
(0059401)
Avishai (reporter)
2012-05-08 15:15

About TPainBox.Canvas size:

That explains why the TButton is also copied. Thanks for the information Mattias Gaertner.
(0059402)
Leonardo M. Ramé (reporter)
2012-05-08 15:22

Thanks Mattias for the info.

> If you want to access the TPaintBox.Canvas outside its OnPaint event you have to move the origin and apply clipping yourself.

Could you give an example of "apply clipping yourself"?. Or, how can I copy the contents of the PaintBox to clipboard?.
(0059413)
Leonardo M. Ramé (reporter)
2012-05-08 20:11

The solution is to create a method like DrawCanvas(ACanvas: TCanvas), then call that method from inside OnPaint, passing PictureBox.Canvas as parameter.

To save to file, or to clipboard, just create an instance of a TBitmap, then call DrawCanvas(myBmp.Canvas);

- Issue History
Date Modified Username Field Change
2012-05-08 00:36 Leonardo M. Ramé New Issue
2012-05-08 00:36 Leonardo M. Ramé File Added: test.tar.gz
2012-05-08 02:18 Avishai Note Added: 0059375
2012-05-08 07:47 Zeljan Rikalo Note Added: 0059377
2012-05-08 13:05 Leonardo M. Ramé Note Added: 0059389
2012-05-08 13:50 Avishai Note Added: 0059390
2012-05-08 14:03 Leonardo M. Ramé Note Added: 0059392
2012-05-08 14:15 Avishai Note Added: 0059393
2012-05-08 14:18 Avishai Note Edited: 0059393
2012-05-08 14:25 Leonardo M. Ramé Note Added: 0059394
2012-05-08 14:31 Avishai Note Added: 0059395
2012-05-08 14:48 Mattias Gaertner Note Added: 0059396
2012-05-08 14:58 Mattias Gaertner Note Added: 0059398
2012-05-08 15:15 Avishai Note Added: 0059401
2012-05-08 15:22 Leonardo M. Ramé Note Added: 0059402
2012-05-08 20:11 Leonardo M. Ramé Note Added: 0059413
2012-06-06 11:39 Zeljan Rikalo Relationship added related to 0022163
2012-06-06 11:41 Zeljan Rikalo Relationship added related to 0020642



MantisBT 1.2.12[^]
Copyright © 2000 - 2012 MantisBT Group
Powered by Mantis Bugtracker