Search code examples
c#wpfdpihighdpi

How can I prevent any and all DPI scaling at all times regardless of monitor for my WPF app?


I have a WPF app that I want to look the same at all times on all DPI scaling settings on any monitor. By this I mean that the app should have the same size in real physical pixels as it has when scaling is set to 100%, at all times.

Currently, the app is scaled up when I start it if DPI scaling is set to anything larger than 100%. I don't want this.

If I give the window a width of 500 pixels, and I can't stress this enough, I expect it to be 500 real physical pixels wide on any and all monitors regardless of DPI scaling.

I tried everything I could find under the sun:

  • Tried all possible combinations of dpiAware and dpiAwareness settings in the app manifest.
  • Tried all values in the "High DPI scaling override" menu on the compatibility properties of my executable.
  • Tried setting DoNotScaleForDpiChanges in the visual studio project file (*.csporj).
  • I read that any programmatic way to do this is futile since the code runs after the process / window is created and therefore scaling is already set, but for the sake of my mental health I still tried it... and failed.

Can this be done or should I just give up and switch over to linux?


Solution

  • WPF isn't intended to work the way you seem to want. Maybe a different technology would suit your purposes better.

    You'd have to reverse the scaling that has been applied.

    I'm not sure why you'd want to do this. If I choose 125% scaling then that's what I want.

    But you can do:

        public MainWindow()
        {
            var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static);
            var dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static);
    
            var dpiX = (int)dpiXProperty.GetValue(null, null) / 96d;
            var dpiY = (int)dpiYProperty.GetValue(null, null) / 96d;
    
            InitializeComponent();
    
            Height /= dpiY;
            Width /= dpiX;
    

    I get a smaller window when I use that calculation. dpiY and dpiX come out as 1.25.

    You don't mention anything about what you have in that window but you will also want to scale the content of course and a viewbox or some such is likely advisable.

    Which would be a nuisance for me with most apps really.

    Probably best not rolling your app out to users have 8k monitors.

    If you are interested in precise content sizing then maybe you should be setting content width and height, make the window sizetocontent.