【问题标题】:Screen Capture program copies more than selected area屏幕捕获程序复制的区域多于选定区域
【发布时间】:2018-12-18 03:06:01
【问题描述】:

我跟随 Huw Collingbourne 程序用 C# 创建了一个屏幕捕获程序。但是,我注意到了一些奇怪的项目,无论我使用他创建的程序还是我修改的程序都一样。具体来说,我创建了一个程序,该程序打开一个窗口,允许您捕获该区域。 我认为这与坐在我的电脑上有关,但如果其他人要使用我的屏幕捕获程序,需要知道如何预测和解决这个问题! 如果我的 windows 10 显示设置为 100%,我得到的比选定的窗口多一点,如果我将显示设置为 125% 的文本,那么我得到很多选定的区域。保留默认大小,我的大小应该是 555、484。但我捕获的要大得多。

public partial class Form1 : Form
{
    //https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowrect
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")]
    private static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle lpRect);

    //ICON info
    //https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getcursorinfo
    [DllImport("user32.dll")]
    private static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
    [DllImport("user32.dll")]
    private static extern bool GetCursorInfo(out CURSORINFO pci);


    public struct POINT
    {
        public Int32 x;
        public Int32 y;
    }

    public struct ICONINFO
    {
        public bool fIcon;
        public Int32 xHotspot;
        public Int32 yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
    }

    public struct CURSORINFO
    {
        public Int32 cbSize;
        public Int32 flags;
        public IntPtr hCursor;
        public Point ptScreenPos;
    }

    GrabRegionForm grabForm;

    public void GrabRect(Rectangle rect)
    {
        int rectWidth = rect.Width - rect.Left;
        int rectHeight = rect.Height - rect.Top;
        Bitmap bm = new Bitmap(rectWidth, rectHeight);
        Graphics g = Graphics.FromImage(bm);
        g.CopyFromScreen(rect.Left, rect.Top, 0, 0, new Size(rectWidth, rectHeight));
        DrawMousePointer(g, Cursor.Position.X - rect.Left, Cursor.Position.Y - rect.Top);
        this.pb_screengrab.Image = bm;
        Clipboard.SetImage(bm);
    }
}

public partial class GrabRegionForm : Form
{
    public Rectangle formRect;
    private Form1 mainForm;
    [DllImport("user32.dll")]
    public static extern bool ReleaseCapture();
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    private void buttonOK_Click(object sender, EventArgs e)
    {
        formRect = new Rectangle(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height);
        this.Hide();
        mainForm.GrabRect(formRect);
        Close();
    }
}

ScreenGrab with Display at 100%

ScreenGrab with Display at 125%

Area showing capture window

Area Actually Captured

【问题讨论】:

  • 在此处查看注释:Image is not drawn at the correct spot
  • 另外,如果您的应用程序不是 DPIAware,它会受到虚拟化的影响,这意味着系统会自动对其进行扩展。这意味着所有与屏幕相关的度量和 DPI 值也是虚拟化的。如果是这种情况,请参阅此处:How to configure an app to run correctly on a machine with a high DPI setting。我写了一些关于这个主题的笔记here
  • 感谢 Jimi 完美的工作!!!
  • 更正。感谢 Jimi 为区域屏幕和屏幕捕获显示 1 完美工作。但不幸的是,第二个显示屏幕捕获失败。
  • 阅读这些注释:Using SetWindowPos with multiple monitors 并重新阅读第一个链接中的注释。您需要根据源 DPI 设置位图 DPI。因此,您需要屏幕 DPI 并使用该信息来设置您的位图 DPI。否则,将使用默认的 96 dpi。在 Windows 10 中,默认(主)屏幕 DPI,

标签: c# winforms screenshot dpi


【解决方案1】:

如果使用早于 4.7 而不是 Windows 10 的用户,请遵循 Jimi 的示例,并确保您退出并重新登录 Windows。

来自吉米https://stackoverflow.com/users/7444103/jimi 如何配置应用程序以在具有高 DPI 设置的机器上正确运行How to configure an app to run correctly on a machine with a high DPI setting (e.g. 150%)?

来自吉米https://stackoverflow.com/users/7444103/jimi 多显示器使用 SetWindowPos Using SetWindowPos with multiple monitors

如果我将我的应用程序定位到 Windows 10 Only 它现在非常简单。 如果使用 Windows 10,Microsoft 使用 4.7 可以更轻松地更改 DPI 设置。

https://docs.microsoft.com/en-us/dotnet/framework/winforms/high-dpi-support-in-windows-forms

声明与 Windows 10 的兼容性。 然后将以下内容添加到 XML 中的 app.manifest 文件中,用于 Windows 10 兼容性。

supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"

在 app.config 文件中启用每个显示器的 DPI 感知。 Windows 窗体引入了一个新元素,以支持从 .NET Framework 4.7 开始添加的新功能和自定义项。要利用支持高 DPI 的新功能,请将以下内容添加到您的应用程序配置文件中。

转到 System.Windows.Forms.ApplicationConfigurationSection 的 XML 行

add key="DpiAwareness" value="PerMonitorV2"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 2019-03-22
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    相关资源
    最近更新 更多