WPF中的屏幕分辨率问题?

27

我将使用以下代码在WPF中检测分辨率:

double height = System.Windows.SystemParameters.PrimaryScreenHeight;
double width = System.Windows.SystemParameters.PrimaryScreenWidth;

我的屏幕当前分辨率为1920*1200,但是height是960.0,width是1536.0 !!!

有什么问题吗?
提前致谢。

8个回答

37
请记住,所有WPF的位置和大小都是浮点数,单位为1/96英寸,而不是像素。这使得您的窗口设计与分辨率无关。通过以下计算:高度=960/96 = 10英寸。如果你的视频适配器设置为120 DPI(120/96 = 125%):10 * 120 = 1200像素。宽度也是一样的:1536/96 * 120 = 1920像素。
System.Windows.Forms使用像素作为单位。您在高度上获得少于1050像素,因为它减去了任务栏的高度。但对于WPF,您始终要使用1/96英寸,而不是像素。

27

为了实现更加稳健的程序,您应该在系统上计算DPI因素并使用这些因素进行操作。正常DPI值为96,但某些显示器可能具有不同的值。要考虑到您的代码可能在具有不同DPI值的显示器上运行。考虑以下代码:

    private static void CalculateDpiFactors()
    {
        Window MainWindow = Application.Current.MainWindow;
        PresentationSource MainWindowPresentationSource = PresentationSource.FromVisual(MainWindow);
        Matrix m = MainWindowPresentationSource.CompositionTarget.TransformToDevice;
        thisDpiWidthFactor = m.M11;
        thisDpiHeightFactor = m.M22;
    }

然后您可以使用这些比率来获得最终值:

CalculateDpiFactors();
double ScreenHeight = SystemParameters.PrimaryScreenHeight * thisDpiHeightFactor;
double ScreenWidth = SystemParameters.PrimaryScreenWidth * thisDpiWidthFactor;

屏幕高度和宽度的值应该与您在显示器属性窗口中看到的相匹配。


4
可以,但你提前有一个窗口。如何计算没有窗口的 DPI?这应该是可能的 - DPI 是桌面的属性,而不仅仅是窗口的属性。 - greenoldman
谢谢,这非常有帮助。 - Vladimir Amiorkov
这里似乎有一些与此相关的代码:https://www.mesta-automation.com/tecniques-scaling-wpf-application/ - Beachwalker

2
请在 Windows 加载完成后调用此函数。
 public static class Ext
{
    public static Size GetNativePrimaryScreenSize(this Window window)
    {
        PresentationSource mainWindowPresentationSource = PresentationSource.FromVisual(window);
        Matrix m = mainWindowPresentationSource.CompositionTarget.TransformToDevice;
        var dpiWidthFactor = m.M11;
        var dpiHeightFactor = m.M22;
        double screenHeight = SystemParameters.PrimaryScreenHeight * dpiHeightFactor;
        double screenWidth = SystemParameters.PrimaryScreenWidth * dpiWidthFactor;

        return new Size(screenWidth, screenHeight);
    }
}

1

尝试使用 SystemParameters.FullPrimaryScreenWidth 和 FullPrimaryScreenHeight,我相信 PrimaryScreenWidth 和 Height 返回的是屏幕上除任务栏和其他桌面工具栏后可用客户端窗口的大小。


0

我已经测试过了,结果和我之前的第一篇帖子一样! - Mohammad Dayyan
好奇怪。如果你从控制面板更改屏幕分辨率会发生什么? - Rob Fonseca-Ensor
我将分辨率更改为1680*1050,结果:高度=1002.0;宽度=1680.0。顺便说一句:DPI为125%。 - Mohammad Dayyan

0
如果您勾选了“使用Windows XP样式的DPI缩放”,那么“Screen.PrimaryScreen.Bounds”的返回值是正确的。如果没有勾选,则返回值将按DPI值成比例缩小(这是默认设置)。
要找到“使用Windows XP样式的DPI缩放”复选框,请展开以下链接中的“为那些未设计高DPI的程序使文本和屏幕项目更清晰”链接: http://windows.microsoft.com/zh-cn/windows-vista/Make-the-text-on-your-screen-larger-or-smaller

请注意:该链接现在自动跳转到Windows 8.x的说明,而不是XP / Vista / Win7。 - Clint StLaurent

0
你可以使用这个:
float dpiX, dpiY;
using (Graphics graphics = Graphics.FromHwnd(IntPtr.Zero))
{
     dpiX = graphics.DpiX;
     dpiY = graphics.DpiY;
}

double screenX = SystemParameters.PrimaryScreenWidth / 96 * dpiX;
double screenY = SystemParameters.PrimaryScreenHeight / 96 * dpiY;

-1

尝试这些...我相信这可以纠正错误...

System.Windows.Form1.Screen.PrimaryScreen.Bounds.Height; System.Windows.Form1.Screen.PrimaryScreen.Bounds.Widtht;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接