1
votes

I found a WPF app which declares itself Per-Monitor DPI aware in the application manifest runs as System DPI aware when it is executed in Visual Studio 2013 (both debug and release). The app runs as Per-Monitor DPI aware when stand alone. I created an app which has exactly the same code in Visual Studio 2012 Express for Windows Desktop and in that case, it runs as Per-Monitor DPI aware even in Visual Studio.

So I think something in Visual Studio 2013 prevents the app from running as Per-Monitor DPI aware. Does anyone has a clue or suggestion?

The code behind of test app is as follows:

using System;
using System.Runtime.InteropServices;
using System.Windows;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);

        var awareness = GetDpiAwareness();
        if (awareness.HasValue)
            this.Title = awareness.Value.ToString();
    }

    private PROCESS_DPI_AWARENESS? GetDpiAwareness()
    {
        var ver = Environment.OSVersion.Version;
        if (!((6 == ver.Major && 3 <= ver.Minor) || (7 <= ver.Major)))
            return null;

        PROCESS_DPI_AWARENESS value;
        var result = GetProcessDpiAwareness(IntPtr.Zero, out value);
        if (result != 0)
            return null;

        return value;
    }

    [DllImport("Shcore.dll")]
    private static extern int GetProcessDpiAwareness(IntPtr hprocess, out PROCESS_DPI_AWARENESS value);

    private enum PROCESS_DPI_AWARENESS
    {
        Process_DPI_Unaware = 0,
        Process_System_DPI_Aware = 1,
        Process_Per_Monitor_DPI_Aware = 2
    }
}

and the application manifest is as follows:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
    </application>
  </compatibility>

  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>True/PM</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

</asmv1:assembly>
1
Your code doesn't look much like the recommended way to do this. At least try the sample app to verify if this actually has anything to do with running with a debugger. If it does then disabling the Hosting process would be a random thing to try.Hans Passant
@Hans Thanks for your commment. This app is intended to check if the app is recognized as Per-Monitor DPI aware by the OS because it is prerequisite to receive the WM_DPICHANGED message from the OS. Using the application manifest to notify this app is Per-Monitor DPI is recommended way.emoacht
Pretty sure I gave you a link for the "recommended way" for a WPF app. It is not that straight-forward for WPF since it already has system DPI awareness built in. If you don't want to use my recommendation then that's okay, it doesn't matter that much anyway since it works fine without a debugger.Hans Passant
@Hans I have tried "Per-Monitor Aware WPF Sample" and it worked fine. It uses SetProcessDpiAwareness function to notify the OS it is Per-Monitor DPI aware. On the other hand, MSDN says "We recommend that you use the application manifest because that sets the DPI awareness level when the application is launched. Use the API only in the following cases:" So I edited the sample to use the application manifest instead of SetProcessDpiAwareness function and the sample showed that it is not Per-Monitor DPI aware in VS2013.emoacht

1 Answers

3
votes

As Hans suggested on disabling the Hosting process, this problem seem to be resulted from known issue of Visual Studio 2013 which ignores the application manifest in the debegger.

So, I tried Visual Studio 2013 Update 3 RC and then the problem has gone. This issue seems to be fixed in Update 3. Now the application manifest is properly reflected and the test app is recognized as Per-Monitor DPI in VS2013. That's it.