Как исправить CopyFromScreen, используя несколько мониторов с DPI 125% - PullRequest
0 голосов
/ 29 июня 2019

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

Моя проблема в том, что, когда я переместил свой монитор со своих внешних мониторов на главный экран моего ноутбука, область захвата была смещена на непоследовательную величину. Я наконец-то понял, что виновато масштабирование (DPI). Когда я изменил его на 100% (96 DPI), он работал на экране ноутбука. Все остальные экраны уже были установлены на 100%. Вернуться к 125%, и это была только проблема на экране ноутбука. Как мне разрешить 125%?

Находясь на экране ноутбука, чем ближе к верхнему левому краю экрана находится форма, тем точнее местоположение изображения. Размер сгенерированного изображения одинаков на любом экране, только местоположение меняется на экране ноутбука. Кроме того, форма изменяется при переходе с внешнего монитора на дисплей ноутбука. Именно после этого изменения размера я получаю эту проблему.

    private void capture(Control ctrl, string fileName)
    {
        Rectangle bounds = ctrl.Bounds;
        Point pt = ctrl.PointToScreen(bounds.Location);
        Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.CopyFromScreen(new Point(pt.X - ctrl.Location.X, pt.Y - ctrl.Location.Y), Point.Empty, bounds.Size);
        }
        string filetype = fileName.Substring(fileName.LastIndexOf('.')).ToLower();
        switch (filetype)
        {
            case ".png":
                bitmap.Save(fileName, ImageFormat.Png);
                break;
            case ".jpeg":
                bitmap.Save(fileName, ImageFormat.Jpeg);
                break;
            case ".bmp":
                bitmap.Save(fileName, ImageFormat.Bmp);
                break;
            default:
                break;
        }
    }

Ответы [ 2 ]

0 голосов
/ 09 июля 2019

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

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

private void capture(Control ctrl, string fileName)
{
    Bitmap bitmapForm = new Bitmap(this.Width, this.Height);
    this.DrawToBitmap(bitmapForm, new Rectangle(0, 0, this.Width, this.Height));
    Rectangle myControlRect = new Rectangle(ctrl.Location,ctrl.Size);
    //Correct for boarder around form
    myControlRect.Offset(8,31);
    Bitmap bitmap = bitmapForm.Clone(myControlRect, PixelFormat.DontCare);
    string filetype = fileName.Substring(fileName.LastIndexOf('.')).ToLower();
    switch (filetype)
    {
        case ".png":
            bitmap.Save(fileName, ImageFormat.Png);
            break;
        case ".jpeg":
            bitmap.Save(fileName, ImageFormat.Jpeg);
            break;
        case ".bmp":
            bitmap.Save(fileName, ImageFormat.Bmp);
            break;
        default:
            break;
    }
}
0 голосов
/ 29 июня 2019

Я не уверен, как вы получили правильную часть экрана, скопированную с вашим текущим кодом. Свойство Bounds () возвращает прямоугольник относительно элемента управления PARENT , но вы просили сам элемент управления (не родительский) преобразовать в координаты экрана:

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

Я бы ожидал увидеть что-то похожее на:

Rectangle bounds = ctrl.Parent.RectangleToScreen(ctrl.Bounds);       
Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
    g.CopyFromScreen(bounds.Location, new Point(0,0), bounds.Size);
}

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

...