I've been trying to disable the DPI awareness on a ClickOnce application.
I quickly found out, it is not possible to specify it in the manifest, because ClickOnce does not support asm.v3 in the manifest file.
The next option I found was calling the new Windows function SetProcessDpiAwareness.
According to this tutorial,
Call SetProcessDpiAwareness before you create the application window.
And this tutorial,
you must call SetProcessDpiAwareness prior to any Win32API call
You have to call the function pretty early on. So, to test, I have created an entirely blank WPF application, and made this my entire App class:
[DllImport("SHCore.dll", SetLastError = true)]
private static extern bool SetProcessDpiAwareness(PROCESS_DPI_AWARENESS awareness);
[DllImport("SHCore.dll", SetLastError = true)]
private static extern void GetProcessDpiAwareness(IntPtr hprocess, out PROCESS_DPI_AWARENESS awareness);
private enum PROCESS_DPI_AWARENESS
{
Process_DPI_Unaware = 0,
Process_System_DPI_Aware = 1,
Process_Per_Monitor_DPI_Aware = 2
}
static App()
{
var result = SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_DPI_Unaware);
var setDpiError = Marshal.GetLastWin32Error();
MessageBox.Show("Dpi set: " + result.ToString());
PROCESS_DPI_AWARENESS awareness;
GetProcessDpiAwareness(Process.GetCurrentProcess().Handle, out awareness);
var getDpiError = Marshal.GetLastWin32Error();
MessageBox.Show(awareness.ToString());
MessageBox.Show("Set DPI error: " + new Win32Exception(setDpiError).ToString());
MessageBox.Show("Get DPI error: " + new Win32Exception(getDpiError).ToString());
}
The 3 message boxes show this content:
Dpi set: True
Process_System_DPI_Aware
Set DPI error: System.ComponentModel.Win32Exception (0x80004005): Access is denied
System.ComponentModel.Win32Exception (0x80004005): The operation completed successfully
Why is the application still set to DPI_Aware? Is this call not early enough?
The application does indeed experience DPI scaling.
When I use the manifest definition:
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
</windowsSettings>
</application>
It does return Process_DPI_Unaware.
EDIT 1:
Now grabbing Marshal.GetLastWin32Error() directly after pInvoke methods, this now actually returns an error.