mackenir
mackenir

Reputation: 10989

Prevent my Win32 application's UI elements from being scaled up when high DPI is set

When windows is set to "resize text to "125%", my Win32 application has its UI (but not its window size) scaled up. This causes text strings to be cut off and UI elements to disappear off the edge of the window.

I would like to prevent this from happening, so that text isn't scaled up, and the app displays correctly. As the time investment to get this old legacy app properly DPI-aware is too high, and I just want to make the app usable by preventing Windows from breaking the UI by resizing UI elements.

I have tried calling SetProcessDPIAware() during startup, and when that didn't work, signalling that the app is DPI Aware in its manifest. However, neither of these measures has any effect.

The manifest fragment I am using to specify DPI awareness:

<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <asmv3:application
           xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
      xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

Upvotes: 4

Views: 9658

Answers (5)

wking
wking

Reputation: 51

if you use visual studio, you can set "DPI Awareness" options to "None" to disable DPI scale.

Project Property -> Manifest Tool -> Input and Output -> DPI Awareness : None

no DPI scale

Upvotes: 0

selbie
selbie

Reputation: 104579

On my team's app, we have the xmlns attribute for asmv3 on the assembly attributes instead of on the application attribute.

Instead of this line:

<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>

This line:

<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0' xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">

I took my product's app manifest and stripped it down to just the and parent nodes. Here it is for reference:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

Upvotes: 0

Raptor007
Raptor007

Reputation: 398

I had similar problems with SDL OpenGL. Windows DPI scaling on unaware applications is very poorly implemented, such as zooming in a fullscreen viewport and cropping off the sides.

I didn't have any luck with the manifest.

I was able to solve it by calling SetProcessDPIAware(); but it had to happen before SDLmain executed. Maybe your "during startup" wasn't early enough. I use it as a global variable initializer before the main function:

BOOL dpi_result = SetProcessDPIAware();

int main( int argc, char **argv )
{
    //...

Upvotes: 3

Philip Beck
Philip Beck

Reputation: 385

This is just a word of warning on wrongly suspecting MFC / Windows 7 on this issue.

I had what appeared to be the same problem. Our (older) MFC application, when ran on windows 7 with it's font set to 125%, displayed dialog boxes at the wrong size. The controls were scaled but each dialog was about 25% too small.

At first I searched through the dialog code for anything that might set its size/position. Then I saw that many people online were having trouble with dialog sizes when moving MFC applications to Windows 7, which falsely increased my suspicion of MFC / Windows 7.

Finally I read a similar discussion and found a comment by the maintainer of spy++ that a feature where it saves size/position on exit forced the window into the wrong size after a font / DPI change. Our software was doing the same, but the code was in the main application and not in the dialogs.

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 613461

For a 125% font scaling, the DPI aware setting is not relevant. What happens is that the text will be 25% bigger, and the onus is then on you to scale up your UI to match. Your dialogs will typically need to be 25% larger to accommodate the larger text. Not only do you have to scale the sizes, you also need to scale the positions. It's up to you to code all of that. Or use a UI framework that does it for you.

For font scaling larger than 125%, the DPI aware setting comes into play. What happens is:

  1. If your app is not marked DPI aware, Windows will scale your app using raster image resizing. This will lead to your visual elements being pixellated.
  2. If your app is marked DPI aware, Windows will render your app faithfully. Again, the onus is on you to scale your UI to fit the text.

This MSDN article has all the gory details.

Back to your specific question. You said:

I would like to prevent this from happening, so that text isn't scaled up, and the app displays correctly.

In other words you are saying that you would like to ignore the user's font scaling setting and render at 100% DPI irrespective of their wishes. You can do this by reducing the size of all your text by 25%. I really do not recommend that you do so.

Upvotes: 0

Related Questions