Search code examples
c#wpfwindowsscalingdpi

Is there a way to disable scaling for all the WPF application even if windows has some scale per monitor or system-wide scale?


I need to have WPF windows that is always 1:1 with physical pixels (DPI is always 96), and by this time I found no way to do this: application manifest or API methods for the awareness are useless, they just changing ways how the content is being scaled: as a bitmap or by the application. I need application always has the fixed, 100% scale, even if system settings are 200% per monitor or per whole system. Do you guys know some ways that could help?


Solution

  • For those who will be looking for the similar solution:

    I found no way to force application do not scale together with the operating system, but found how to keep 1:1 scale.

    First thing you need to do is to define that the application is dpi-aware, so it will not be scaled by the system but by application itself. Here is app.manifest code:

    <?xml version="1.0" encoding="utf-8"?>
    <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
      <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
    
      <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings>
          <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
        </windowsSettings>
      </application>
    </assembly>
    

    Then you'll be able to get current scale for the visual:

    double xScale = PresentationSource.FromVisual(someVisual).CompositionTarget.TransformToDevice.M11;
    double yScale = PresentationSource.FromVisual(someVisual).CompositionTarget.TransformToDevice.M22;
    

    And then you could bind layout transform to control (image in my case) to cancel scaling effect:

    <Image.LayoutTransform>
        <ScaleTransform ScaleX="{Binding ElementName=_this, Path=ScaleX}"
                        ScaleY="{Binding ElementName=_this, Path=ScaleY}" />
    </Image.LayoutTransform>
    

    Please note that proportions should be inverted, so ScaleX and ScaleY will have these values:

    ScaleX = 1 / scaleX;
    ScaleY = 1 / scaleY;