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

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

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

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

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

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

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

 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. { } } 

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

希望这可以帮助。

我相信您必须通知操作系统您的应用程序可以识别DPI。 否则操作系统假装一切都很好,导致你正在观察的行为 – 操作系统处理resize。

您可以在此处找到有关编写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之后,无论价值如何)。