I have tried to make Windows 8.1 recognize a Delphi XE6 application (a demo program) that I have been trying to build, and have it recognize my application is Per-Monitor DPI aware, purely by the Manifest technique. Delphi XE6 (and all other similarly up to date versions of Delphi) make adding a manifest easy to do, inside Project Options, and I have done so.
This is the .manifest content I have determined using MSDN resources. I suspect it could be slightly incorrect.
If you want to try this manifest, make an empty VCL application, use this content as your manifest, and add the code (code is currently attached to my answer to this question).
<?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" >
<!-- Per Monitor DPI Awareness in Windows 8.1 uses asmv3:application + asmv3:windowsSettings -->
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<!-- Dear Microsoft, Don't Lie to Me About What Version of Windows I am On -->
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista and Windows Server 2008 -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 and Windows Server 2008 R2 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 and Windows Server 2012 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 and Windows Server 2012 R2 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
</application>
</compatibility>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
Has anyone gotten this to work? What I find is that the above is not recognized. If I call SetProcessDPIAwareness(Process_Per_Monitor_DPI_Aware)
first, then call GetProcessDPIAwareness(hProc,Awareness)
, I get back the necessary Awareness = Process_Per_Monitor_DPI_Aware
, but I have read that there are potential drawbacks to that approach, and so I would prefer a working Manifest-only approach.
If I call GetProcessDPIAwareness(hProc,Awareness)
, I get back `Awareness = Process_DPI_Unaware'.
My other worry is that in the MSDN sources they specify adding an ADDITIONAL manifest. Whereas, I am using Delphi XE6's IDE's ability to link ONE and ONLY ONE manifest into my application. I have never noticed that adding any additional manifest versus having only one was ever a problem, other than that perhaps the .manifest management system in Visual Studio 2010 was lame, and that is why the tip existed, and so has no relevance to other IDEs/Languages.
In Visual Studio 2013, there is a checkbox right inside the project options, but I don't have Visual Studio 2013 so I can't examine a working .manifest.
update:
Here's another shot at a manifest:
<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>
The above mini manifest changes the behavior of the application, but not exactly the way I wanted it to. With the above tiny manifest, the OLD Windows 8.0/Windows 7/Vista DPI awareness level is detected.
update 2:
Thanks Remy for the ideas. Interestingly the following appears to be valid enough to allow an application launch. However mixing the SMI/2005 syntax with the above caused a side-by-side launch error. You can see that Microsoft has been churning on their manifests rather a lot. Note that the following does not actually solve my problem, but it provides yet another "potential base form" that might be CLOSE to the real solution:
<assembly xmlns="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0" >
<application>
<windowsSettings xmlns="http://schemas.microsoft.com/SMI/2011/WindowsSettings">
<dpiAware>true</dpiAware>
</windowsSettings>
</application>
</assembly>
update 3:
CODE RED ALERT! DO NOT USE the following OS COMPATIBILITY flag in any Delphi VCL application:
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
. Microsoft has BROKEN MOUSE CAPTURE BEHAVIOUR, BROKEN WINDOW PAINTING in horrible ways that I have not even been able to guess at. Turning this flag on caused very subtle bugs in my application, including painting problems, inability to click on controls (mouse down messages not reaching controls, due to mouse capture being lost), and many other problems.
<dependency>
be first, then the<compatibility>
next, then finally the<application>
last. These are the order in which those feature were introduced in Windows. XML is not supposed to be order-sensitive, but can be if an XML schema is used. Windows' parser might be order-sensitive, it might need to see the Win8.1<compatibility>
element is present before it will process the<dpiAware>
element. – Corney<WindowsSettings>
element ishttp://schemas.microsoft.com/SMI/2005/WindowsSettings
, the Application Manifests documentation says the namespace ishttp://schemas.microsoft.com/SMI/2011/WindowsSettings
instead, so try both. – Corneyuses PerMonitorApi; ... SomeLabelControl.Visible := SystemCanSupportPerMonitorDpi( False);
– Filberto