如何使用 Control.DrawToBitmap 将 Form 渲染为没有装饰(标题栏、边框)的 Bitmap?

How to use Control.DrawToBitmap to render a Form into a Bitmap without its decorations (titlebar, border)?

我有一个表单,其中有一个覆盖控件(透明的灰色背景,"Drop here..." 上有白色文本和一个图标),仅当将文件拖到表单上时才可见。通过在其背面绘制控件然后用透明灰色 (ARGB) 填充,可以使叠加层透明。当 Overlay 应该覆盖在不是 Form 的 Control 上时,该方法非常有效,但是当我使用 Control.DrawToBitmap 呈现 Form 而不是通常的 Control 时,它还会呈现标题栏和边框。

您可以呈现整个表单,然后使用 Bitmap.Clone() 只提取您需要的部分。 Here 你已经解释了如何去做。

Form.DrawToBitmap 绘制整个表单,包括非客户区。您可以使用 BitBltBitBlt 函数将对应于矩形像素的颜色数据从指定的源设备上下文执行位块传输到目标设备上下文。

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;
}

Control.DrawToBitmap 方法总是 return 从控件的左上角绘制的位图,即使您向该方法传递具有特定边界的矩形也是如此。

此处,表单的 ClientRectangle 部分是 translated 使用其 [ 的大小=12=].

请注意,如果您的应用程序不是 DPIAware,您可能 从 return 点或矩形的所有方法中得到错误的度量。包括非 DPIAware Windows API。

如果您需要保存生成的位图,请使用 PNG 作为目标格式:其无损压缩更适合这种渲染。

调用此方法时将 ClientAreaOnly 参数设置为 true 使其成为 return ClientArea 的位图只有.

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;
}