How can I capture as bitmap only what a picturebox is displaying, without using “copy from screen”?

This will copy and save the currently shown content of the PictureBox including a BackgroundImage (if there is one and if it shines through) and also all Controls that belong to the PictureBox, like Labels etc.. Also included are elements drawn in the Paint event. Things drawn outside the Paint event are non-persistent and will not be included.

using (Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width,
                               pictureBox1.ClientSize.Height))
{
   pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle);
   bmp.Save(yourfilename, ImageFormat.Png);
}

Note: On my test Form the PicureBox is sitting inside an AutoScroll Panel pan_PBscroll. The PictureBox is displaying pixels 1:1 and is therefore, with a photograph loaded, much bigger than the Panel, the Form or even the Screen. So to clip to the actually visible parts I could not use the pictureBox1.ClientSize and pictureBox1.ClientRectangle but used the dimensions of that Panel. This may well apply to you, too.

I’m not sure about your timing issues. But since you mentioned CopyFromScreen here are a few differences:

  • CopyFromScreen makes a 1:1 copy of each screen pixel
  • This includes non-persistent drawings and excludes anything covered or hidden
  • Control.DrawToBitmap makes the Control draw itself onto a Bitmap, just as it draws itself during Paint
  • This excludes anything that doesn’t belong to the Control but includes all members of its Controls collection
  • This also excludes non-persistent drawings but includes the full Size of the Control, whether it fits on the Form or Screen or not and whether it is hidden or covered or not.
  • For Controls with active Scrollbars only the visible parts are copied. To copy all you need to resize it temporarily. Then you can get a complete image of a listbox even if it has a thousand items..

Leave a Comment