1

我正在尝试保存第二台显示器的屏幕截图,它的分辨率/DPI 与主显示器不同(我并不完全熟悉这些术语,所以我不太确定),这是我正在使用的代码:

public void SaveScreenshot(Screen screen)
{
    using (Bitmap bitmap = new Bitmap(screen.Bounds.Width, screen.Bounds.Height))
    {
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            int x = screen.Bounds.Left;
            int y = screen.Bounds.Top;
            int w = screen.Bounds.Width;
            int h = screen.Bounds.Height;
            g.CopyFromScreen(x, y, 0, 0, new Size(w, h));
        }

        bitmap.Save("screenshot.bmp");
    }
}

问题是生成的图像没有完整的图片,相反,它有一个更大的裁剪过的图片。

实际的: 实际的

结果: 结果

我不知道我做错了什么。

4

1 回答 1

0

我设法通过使用 EnumDisplaySettings 来解决它:

using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ScreenResolution
{
    class ScreenResolutionHandler
    {
        const int ENUM_CURRENT_SETTINGS = -1;
        public static Rectangle GetRealRectangle(Screen screen)
        {
            DEVMODE dm = new DEVMODE();
            dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
            EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);
            return new Rectangle(dm.dmPositionX, dm.dmPositionY, dm.dmPelsWidth, dm.dmPelsHeight);
        }

        [DllImport("user32.dll")]
        public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);

        [StructLayout(LayoutKind.Sequential)]
        public struct DEVMODE
        {
            private const int CCHDEVICENAME = 0x20;
            private const int CCHFORMNAME = 0x20;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
            public string dmDeviceName;
            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;
            public int dmPositionX;
            public int dmPositionY;
            public ScreenOrientation dmDisplayOrientation;
            public int dmDisplayFixedOutput;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
            public string dmFormName;
            public short dmLogPixels;
            public int dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
            public int dmICMMethod;
            public int dmICMIntent;
            public int dmMediaType;
            public int dmDitherType;
            public int dmReserved1;
            public int dmReserved2;
            public int dmPanningWidth;
            public int dmPanningHeight;
        }
    }
}

并将原始代码编辑为

public void SaveScreenshot(Screen screen)
{
    Rectangle rect = ScreenResolutionHandler.GetRealRectangle(screen);
    int x = rect.X;
    int y = rect.Y;
    int w = rect.Width;
    int h = rect.Height;

    using (Bitmap bitmap = new Bitmap(w, h))
    {
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.CopyFromScreen(x,y, 0, 0, new Size(w, h));
        }

        bitmap.Save("screenshot.bmp");
    }
}

更新:

正如@Jimi 所建议的那样,最终我必须启用每台显示器的 dpi 感知以在将图像放在表单上时保持图像的质量

应用程序清单

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
        <!-- A list of the Windows versions that this application has been tested on
           and is designed to work with. Uncomment the appropriate elements
           and Windows will automatically select the most compatible environment. -->

        <!-- Windows Vista -->
        <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->

        <!-- Windows 7 -->
        <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />

        <!-- Windows 8 -->
        <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />

        <!-- Windows 8.1 -->
        <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />

        <!-- Windows 10 -->
        <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

    </application>
</compatibility>

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- legacy -->
        <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to pm if pmv2 is not available -->
    </windowsSettings>
</application>
于 2020-02-16T16:48:22.407 回答