Захват графики элемента управления в C#

Для захвата графики элемента управления .NET в растровое изображение программисты могут использовать GDI, чтобы передать то, что изображено на экране, в растровое изображение.

Очень полезно иметь представление изображения. Разработчики могут обрабатывать изображение множеством способов. Другой момент — изображение может быть снова отображено на экране, что открывает способ обработки графики элемента управления .NET.

Класс ControlPaint по сравнению с GDI

Довольно распространенный способ рисования элементов управления .NET "вручную" состоит в использовании класса ControlPaint. В классе ControlPaint имеются статические функции, которые могут изображать обычные элементы управления .NET в графической рабочей области. Например, функция ControlPaint.DrawButton рисует кнопку.

Однако этот класс имеет два недостатка. Первый недостаток — в классе ControlPaint отсутствует поддержка всех элементов управления .NET, не говоря уже о пользовательских элементах управления, созданных разработчиком. Второй недостаток — класс ControlPaint не учитывает стили форматирования, и следовательно отрисованный элемент управления не будет соответствовать остальным элементам управления формы.

Лучший способ захвата элемента управления .NET состоит в рисовании в растровом изображении того, что уже нарисовано на экране. GDI имеет функцию BitBlt, которая позволяет разработчикам C# делать это более эффективно. Функция BitBlt расположена в библиотеке GDI32.dll:

[DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest,
int nXDest,
int nYDest,
int nWidth,
int nHeight,
IntPtr hdcSrc,
int nXSrc,
int nYSrc,
int dwRop);

Как можно заметить, BitBlt может выполнить большую часть работы. Все, что от нас потребуется, это предоставить ей соответствующие значения контекстов устройств для отображения (DC). Одно их них будет DC элемента управления, а второе — DC целевого растрового изображения:

public Bitmap CaptureControl(Control control)
{
    Bitmap controlBmp;
    using (Graphics g1 = control.CreateGraphics())
    {
        controlBmp = new Bitmap(control.Width, control.Height, g1);
        using (Graphics g2 = Graphics.FromImage(controlBmp))
        {
            IntPtr dc1 = g1.GetHdc();
            IntPtr dc2 = g2.GetHdc();
            BitBlt(dc2, 0, 0, control.Width, control.Height, dc1, 0, 0, 13369376);
            g1.ReleaseHdc(dc1);
            g2.ReleaseHdc(dc2);
        }
    }
 
    return controlBmp;
}

Использование кода

Конечно, исходный код имеет некоторые ограничения. Поскольку он захватывает элемент управления .NET путем копирования того, что отрисовывается на экране, то при наличии какого-либо объекта вверху захватываемого элемента управления он также будет скопирован.

Преимущество, очевидно, в том, что эта функция может захватывать любой элемент управления, даже пользовательский, в технически любом состоянии.

Функция DrawToBitmap

Мое внимание привлекло то, что объекты элементов управления в платформе .NET Framework 2.0 и последующих выпусков имеют функцию с именем DrawToBitmap, которая автоматически обрабатывает код, описанный выше, для захвата элемента управления .NET в растровое изображение. Приведенный выше код хорошо подходит для более старых приложений .NET.