I have a Form and in it an Overlay control (transparent gray backcolor with White text over "Drop here..." and an icon) that is visible only when a file is dragged over the Form. The Overlay is made transparent by drawing the control in its back on it and then filling over with transparent gray (ARGB). The method Works very well when the Overlay should be over a Control that is not a Form, but when I use Control.DrawToBitmap
to render a Form, not an usual Control, it also renders the title bar and border.

- 120,393
- 18
- 203
- 398

- 3,343
- 3
- 31
- 57
-
You only need the right Rectangle so the title bar and borders are excluded. Use the form's RectangleToScreen() with Point.Empty and ClientSize. – Hans Passant Feb 11 '19 at 11:19
3 Answers
Form.DrawToBitmap
draws the whole form including non-client area. You can use BitBlt
. The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
const int SRCCOPY = 0xCC0020;
[DllImport("gdi32.dll")]
static extern int BitBlt(IntPtr hdc, int x, int y, int cx, int cy,
IntPtr hdcSrc, int x1, int y1, int rop);
Image PrintClientRectangleToImage()
{
var bmp = new Bitmap(ClientSize.Width, ClientSize.Height);
using (var bmpGraphics = Graphics.FromImage(bmp))
{
var bmpDC = bmpGraphics.GetHdc();
using (Graphics formGraphics = Graphics.FromHwnd(this.Handle))
{
var formDC = formGraphics.GetHdc();
BitBlt(bmpDC, 0, 0, ClientSize.Width, ClientSize.Height, formDC, 0, 0, SRCCOPY);
formGraphics.ReleaseHdc(formDC);
}
bmpGraphics.ReleaseHdc(bmpDC);
}
return bmp;
}

- 120,393
- 18
- 203
- 398
-
This method also works if we need to take screenshots of control, which content is rendered by GPU with Direct3D. – komorra May 28 '22 at 11:08
The Control.DrawToBitmap method always return a Bitmap drawn from the upper-left corner of the control, even if you pass the method a Rectangle with specific bounds.
Here, the ClientRectangle
portion of a Form is translated using the Size of its Bounds
.
Note that, if your application is not DPIAware, you might get wrong measures from all the methods that return a Point or a Rectangle. Non-DPIAware Windows API included.
If you need to save the resulting Bitmap, use PNG
as the destination format: its loss-less compression is better suited for this kind of rendering.
Call this method with the ClientAreaOnly
argument set to true
to have it return a Bitmap of the ClientArea
only.
public Bitmap FormScreenShot(Form form, bool clientAreaOnly)
{
var fullSizeBitmap = new Bitmap(form.Width, form.Height, PixelFormat.Format32bppArgb);
// .Net 4.7+
fullSizeBitmap.SetResolution(form.DeviceDpi, form.DeviceDpi);
form.DrawToBitmap(fullSizeBitmap, new Rectangle(Point.Empty, form.Size));
if (!clientAreaOnly) return fullSizeBitmap;
Point p = form.PointToScreen(Point.Empty);
var clientRect =
new Rectangle(new Point(p.X - form.Bounds.X, p.Y - form.Bounds.Y), form.ClientSize);
var clientAreaBitmap = fullSizeBitmap.Clone(clientRect, PixelFormat.Format32bppArgb);
fullSizeBitmap.Dispose();
return clientAreaBitmap;
}

- 29,621
- 8
- 43
- 61
-
The [Form.DeviceDpi](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.devicedpi) property is available only in .NET Framework v4.7+. – silviubogan Feb 13 '19 at 13:12
-
There are other means to get that value, but it's a broad matter (for comments). It's just a precaution (the reason why it can be usefull you can read here: [Image is not drawn at the correct spot](https://stackoverflow.com/a/51456467/7444103)). If you are aware of this, you can just remove it. It's not absolutely nececessary. – Jimi Feb 13 '19 at 13:16