如何使用 DPI 为 125% 的多台显示器修复 CopyFromScreen

How to fix CopyFromScreen using multiple monitors with DPI of 125%

我写了一个函数,它将接受一个控件和一个文件目标,并将保存控件覆盖的表单区域。

我的问题是,当我从外接显示器移到笔记本电脑的主屏幕时,捕获区域移动的量不一致。我终于弄明白缩放比例 (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;
        }
    }

我不确定您是如何使用当前代码复制屏幕的正确部分的。 Bounds() 属性 returns 一个相对于 PARENT 控件的矩形,但您要求控件本身(而不是父控件)转换为屏幕坐标:

Gets or sets the size and location of the control including its nonclient elements, in pixels, relative to the parent control.

我希望看到更多类似的内容:

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

不过,我不知道这是否能在不同的缩放模式下正常工作。

我找不到修复它的方法。我更改了方法并在表单上使用了 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;
    }
}