屏幕分辨率与Screen.Bounds不匹配

Isa*_*vin 10 c# resolution dpi windows-8.1

我看到通过控制面板设置的分辨率和我的宽屏笔记本电脑的Screen.Bounds输出之间有一个有趣的区别.屏幕为15.5",通过控制面板设置的分辨率为1920x1080.但是当我运行这样的代码时.

Screen[] screens = Screen.AllScreens;
foreach (Screen scr in screens)
{
    Console.WriteLine("Width: " + scr.Bounds.Width + ", Height: " + scr.Bounds.Width);
}
Run Code Online (Sandbox Code Playgroud)

输出显示我的分辨率为1536x864.我做了一些环顾四周,我认为它可能与DPI问题有关,当我查看我的显示设置时,滑块(我在Windows 8.1上)位于中间,复选框指出"让我为我的所有显示选择一个缩放级别"未选中.我运行这个小代码来获取当前的DPI设置.

float dpiX, dpiY;
Graphics graphics = new System.Windows.Forms.Form().CreateGraphics();
Console.WriteLine("DPI: " + graphics.DpiX);
Run Code Online (Sandbox Code Playgroud)

返回的DPI是96.0,根据我的理解,这是100%DPI设置(因此没有放大或其他任何调用).对我来说似乎很奇怪的是,Screen返回的界限恰好是我实际分辨率的80%,这会让我认为我的DPI设置为100(或125%),但事实并非如此.我的笔记本电脑屏幕只有这个问题,因为我的辅助显示器的界限等于通过控制面板的分辨率.这是因为我的DPI设置未设置为使显示器彼此独立(选中该复选框)?对于一些背景知识,我正在编写一个工具,它可以获取当前屏幕并从reddit获取图片并将它们彼此独立地放到屏幕上,所以无论我有什么解决方案,它都必须正确地获得每个显示器的分辨率.

nam*_*0ne 10

我对屏幕截图工具也有同样的问题.我找到了解决方案,它对我有用.

private enum ProcessDPIAwareness
{
  ProcessDPIUnaware = 0,
  ProcessSystemDPIAware = 1,
  ProcessPerMonitorDPIAware = 2
}

[DllImport("shcore.dll")]
private static extern int SetProcessDpiAwareness(ProcessDPIAwareness value);

private static void SetDpiAwareness()
{
  try
  {
    if (Environment.OSVersion.Version.Major >= 6)
    {
      SetProcessDpiAwareness(ProcessDPIAwareness.ProcessPerMonitorDPIAware);
    }
  }
  catch (EntryPointNotFoundException)//this exception occures if OS does not implement this API, just ignore it.
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

您应该在调用函数之前调用SetDpiAwareness()方法以获得系统解析等.此外,如果您的应用程序中有一些UI,则您有责任在具有高DPI的屏幕中扩展UI.

希望这可以帮助.

  • 一件事,在Windows 7上不需要使用此代码来缩放分辨率,但是如果此代码在Windows 7上运行,请尝试catch无法捕获所引发的错误,这会使程序崩溃。您需要更改它正在检查的错误,或者就我而言,我只是将其设置为捕获任何异常。 (2认同)

Lua*_*aan 4

我相信您必须通知操作系统您的应用程序支持 DPI。否则,操作系统会假装一切正常,从而导致您所观察到的行为 - 操作系统会处理大小调整。

您可以在这里找到一些有关编写 DPI 感知应用程序的信息 - http://msdn.microsoft.com/cs-cz/library/dd464646.aspx当然,您应该确保您的应用程序实际上DPI 感知的 - 如果不是,你最好坚持默认值。它不是那么好,但至少它会起作用。

Windows 8.1 带来的主要区别是,您可以在不同的显示器上拥有不同的 DPI,并且可以查询显示器 DPI API。.NET(尤其是 WPF)默认情况下会自动处理 DPI 感知,但仅基于系统 DPI。如果您的显示器具有不同的 DPI 设置,它将表现为非 DPI 感知(更准确地说,系统 DPI 感知,但最终结果是您的应用程序图形将被 Windows 虚拟化)。我希望如果您断开第二个显示器的连接,您的应用程序将在您的唯一显示器上按预期运行(至少在手动设置 DPI 之后,无论值是多少)。