C # /. Чистый код для захвата экрана нескольких мониторов с масштабированием - PullRequest
0 голосов
/ 21 сентября 2018

У нас есть большая программа WinForm C # .Net 4.6, которая время от времени должна получать снимки экрана для целей отладки.В настоящее время мы используем этот код:

private static void DoScreenCapture(string filename)
{
    // Determine the size of the "virtual screen", including all monitors.
    int screenLeft = SystemInformation.VirtualScreen.Left;
    int screenTop = SystemInformation.VirtualScreen.Top;
    int screenWidth = SystemInformation.VirtualScreen.Width;
    int screenHeight = SystemInformation.VirtualScreen.Height;

    // Create a bitmap of the appropriate size to receive the screenshot.
    using (Bitmap bmp = new Bitmap(screenWidth, screenHeight))
    {
        // Draw the screenshot into our bitmap.
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.CopyFromScreen(screenLeft, screenTop, 0, 0, bmp.Size);
        }

        // Stuff the bitmap into a file
        bmp.Save(filename, Imaging.ImageFormat.Png);
    }
}

Этот код делает все, что мы хотим, кроме случаев, когда пользователь масштабирует свои мониторы.

Я смотрел на связки статей переполнения стека.Большинство из них предоставляют код, который у нас уже есть, но он не решает проблему масштабирования монитора.Например:

Сделайте снимок экрана нескольких рабочих столов со всеми видимыми приложениями и формами

В некоторых статьях Stack Overflow указывается, что информирование нашего приложения о DPI решит проблему.Да, было бы, но это больше, чем мы можем решить сегодня.Например:

Снимок экрана Windows с масштабированием

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

Может кто-нибудь дать мне фрагмент кода C #, который сделает снимок экрана с несколькими мониторами с различными коэффициентами масштабирования?

Например, если у меня три идентичных 1920x1080контролирует и размещает их слева направо с крайним левым монитором на 175%, центральным монитором на 100% и крайним правым монитором на 150%, тогда это будет скриншот, который я хочу:

Ожидаетсяснимок экрана

Но это скриншот, который создает мой текущий код.Обратите внимание, что в крайнем правом мониторе отсутствует фрагмент в крайнем правом углу.

Фактический снимок экрана

1 Ответ

0 голосов
/ 22 сентября 2018

Самый простой способ - создать широкое изображение, разрешение которого было построено, используя количество экранов * ширину экрана. Таким образом, у вас есть широкое изображение, которое содержит скриншот всех мониторов и не заботится о масштабировании.

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

Вы можете увидеть эту проблему на изображении ниже.:

enter image description here

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

enter image description here

        int screenCount = Screen.AllScreens.Length;

        int screenTop = SystemInformation.VirtualScreen.Top;
        int screenLeft = SystemInformation.VirtualScreen.Left;
        int screenWidth = Screen.AllScreens.Max(m => m.Bounds.Width);
        int screenHeight = Screen.AllScreens.Max(m => m.Bounds.Height);

        bool isVertical = (SystemInformation.VirtualScreen.Height < SystemInformation.VirtualScreen.Width);

        if (isVertical)
            screenWidth *= screenCount;
        else
            screenHeight *= screenCount;

        // Create a bitmap of the appropriate size to receive the screenshot.
        using (Bitmap bmp = new Bitmap(screenWidth, screenHeight, PixelFormat.Format32bppPArgb))
        {
            // Draw the screenshot into our bitmap.
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.CopyFromScreen(screenLeft, screenTop, 0, 0, bmp.Size);
            }

            // Make black color transparent
            bmp.MakeTransparent(Color.Black);

            bmp.Save("TestImage.png", ImageFormat.Png);
        }
  • Код можно улучшить, чтобы уменьшить окончательный размер изображения, изменив его размер.
  • Вы можете получить разрешение и масштаб каждого монитора с помощью встроенного API и построить окончательное изображение на основе этого размера.
...