我看到通过控制面板设置的分辨率与我的宽屏笔记本电脑的Screen.Bounds输出之间存在一个有趣的区别。屏幕为15.5“,通过控制面板设置的分辨率为1920x1080。但是当我运行这样的代码时。
Screen[] screens = Screen.AllScreens;
foreach (Screen scr in screens)
{
Console.WriteLine("Width: " + scr.Bounds.Width + ", Height: " + scr.Bounds.Width);
}
输出显示我的分辨率为1536x864。我做了一些环顾四周,我认为它可能与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获取图片并将它们彼此独立地放到屏幕上,所以无论我有什么解决方案,它都必须正确地获得每个显示器的分辨率。
答案 0 :(得分: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.
{
}
}
你应该在调用函数之前调用SetDpiAwareness()方法来获得系统解析等。 此外,如果您的应用程序中有一些UI,则您有责任在具有高DPI的屏幕中扩展UI。
希望这有帮助。
答案 1 :(得分: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后,无论价值如何)。