Как использовать Control.DrawToBitmap для рендеринга формы в растровое изображение без его декораций (заголовок, граница)?

У меня есть форма и в ней элемент управления Overlay (прозрачный серый фон с белым текстом над "Drop here..." и значком), который виден только при перетаскивании файла поверх формы. Наложение делается прозрачным, рисуя на нем задний элемент управления, а затем заливая его прозрачным серым (ARGB). Метод работает очень хорошо, когда наложение должно быть над элементом управления, который не является формой, но когда я использую Control.DrawToBitmap для отображения формы, а не обычного элемента управления, она также отображает строку заголовка и границу.

3 ответа

Решение

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

Метод Control.DrawToBitmap всегда возвращает растровое изображение, нарисованное из левого верхнего угла элемента управления, даже если вы передаете методу Rectangle с конкретными границами.

Здесь ClientRectangle часть формы переводится с использованием размера ее Bounds,

Обратите внимание, что если ваше приложение не является DPIAware, вы можете получить неправильные значения из всех методов, которые возвращают точку или прямоугольник. Не-DPIAware Windows API включен.

Если вам нужно сохранить полученное изображение, используйте PNG в качестве формата назначения: его сжатие без потерь лучше подходит для этого вида рендеринга.

Вызовите этот метод с ClientAreaOnly аргумент установлен в true чтобы он вернул растровое изображение 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();
}

Вы можете визуализировать всю форму, а затем взять только ту часть, которая вам нужна Bitmap.Clone(), Здесь вы объяснили, как это сделать.

Другие вопросы по тегам