如何使用Control.DrawToBitmap将表单呈现为没有其装饰(标题栏,边框)的位图? [重复]

问题描述 投票:1回答:3

这个问题在这里已有答案:

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

c# .net winforms gdi+ drawtobitmap
3个回答
1
投票

Form.DrawToBitmap绘制了包括非客户区在内的整个表格。你可以使用BitBlt。 BitBlt函数执行对应于来自指定源设备上下文的像素矩形的颜色数据的位块传输到目标设备上下文。

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

2
投票

Control.DrawToBitmap方法始终返回从控件左上角绘制的位图,即使您将方法传递给具有特定边界的Rectangle也是如此。

在这里,表格的ClientRectangle部分使用其Bounds的大小进行翻译。

请注意,如果您的应用程序不是DPIAware,则可能会从返回Point或Rectangle的所有方法中获得错误的度量。包括非DPIAware Windows API。

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

使用设置为ClientAreaOnlytrue参数调用此方法,使其仅返回ClientArea的位图。

public Bitmap FormScreenShot(Form form, bool ClientAreaOnly)
{
    Bitmap 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);
    Rectangle clientRect =
        new Rectangle(new Point(p.X - form.Bounds.X, p.Y - form.Bounds.Y), form.ClientSize);

    Bitmap clientAreBitmap = fullSizeBitmap.Clone(clientRect, PixelFormat.Format32bppArgb);
    fullSizeBitmap.Dispose();
    return (Bitmap)clientAreBitmap.Clone();
}

0
投票

您可以渲染整个表单,然后只使用Bitmap.Clone()所需的部分。 Here你已经解释了如何做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.