-2

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?

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
user1969903
  • 810
  • 13
  • 26
  • I would think carefully about what you are trying to do here. For example if your monitor is standard Full HD monitor with resolution of 1920x1080 then on a monitor that is 24" 500 px will be roughly 138 mm, the same monitor with 4K resolution your 500 px is about 69 mm. That would also be applied to contents so any writing that is almost 70 mm in width would not be very readable. Maybe you should use different units instead like cm or inch? – XAMlMAX Jan 26 '23 at 15:19
  • This is a bit long winded comment but I have in past tried to implement zoom functionality, which was using render transform. Maybe you could try it there? Assuming your window would scale as normal but content could be transformed based on DPI? It's just a thought and that is assuming content can be different than the containing window. – XAMlMAX Jan 26 '23 at 15:21
  • 1
    @XAMlMAX no no, I know exactly what the OP is talking about and why they have to do this. They've inherited a legacy app that probably predates the popularity of font scaling and has hard coded dimensions everywhere. But because font scaling isn't 100% pixel perfect text inside buttons and other boxes is probably being cut off all over the place. This is not an enviable position to be in and I understand why this option would be explored. – Emperor Eto Jan 26 '23 at 16:28
  • 1
    Thanks @PeterMoore that makes sense. I feel sorry for you and OP. So long story short, you are better of going through offending areas and fixing it rather than looking for a quick fix. Should your manager say otherwise send him this way. – XAMlMAX Jan 26 '23 at 16:34
  • @PeterMoore you, sir, are spot on. – user1969903 Jan 30 '23 at 06:08
  • @XAMlMAX Mostly all of my apps are DPI aware. Mostly. This one is a special little ugly duckling. – user1969903 Jan 30 '23 at 06:17

1 Answers1

0

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.

Andy
  • 11,864
  • 2
  • 17
  • 20
  • 1
    The app is very configurable. It has a user setting for most options. Menu width, font size, widget size, toolbar height, font color, background color, etc. etc. The idea is that the app is configured by an admin how he wants it and then rolls it out to a group of users but some users who use DPI scaling complain about how the app looks on their system. It's a legacy app I've inherited, I don't have much control over it. – user1969903 Jan 26 '23 at 10:14
  • In any case, you're saying that there is no way to achieve what I want other than reversing every scaling everywhere it is applied? – user1969903 Jan 26 '23 at 10:15
  • Everywhere? This is one place. Maybe scale your content and make the window fit to it. – Andy Jan 26 '23 at 10:17
  • The app consists of multiple windows (think widgets) and their position is customizable by the user. When DPI scaling is set, the position is out of whack so I'd have to account for the scaling. Hence, "everywhere". That's why I was hoping there was some registry or some app config property that I've missed and that I can change and have windows ignore the entire app and stop scaling it. I also have to account for it for every other dimensional setting (menu width, etc.) – user1969903 Jan 26 '23 at 10:21
  • menus are content. Scale the content of a window and everything in it is scaled. You could write one piece of code and apply to any and all windows. – Andy Jan 26 '23 at 10:28
  • @user1969903 you might be able to assign a `ScaleTransform` to the `LayoutTransform` of the Window based on the dpi values you'd get here and only have to do that in one place. I don't know if that would work for Menus and other Popups that aren't part of the main window, but it should work for the overwhelming majority of your content. – Emperor Eto Jan 26 '23 at 16:17
  • That's a good point @Peter Moore – Andy Jan 26 '23 at 16:20
  • There is of course a registry entry you could change. The user's display preference is stored in the registry. Changing a user's 125% display scaling to 100% might not be so popular. Maybe highlighting why nobody does this reversing the users preferences thing. – Andy Jan 26 '23 at 16:22
  • 1
    @Andy Ended up creating a converter and using that for the XAML bindings that require scaling (including window dimensions) and that did the heavy lifting. A few other tweaks here and there and it's looking good. – user1969903 Jan 30 '23 at 06:11