【发布时间】:2015-01-07 05:59:33
【问题描述】:
我试图让 Windows 8.1 识别我一直在尝试构建的 Delphi XE6 应用程序(一个演示程序),并让它识别我的应用程序是 Per-Monitor DPI 感知的,纯粹是通过 Manifest 技术。 Delphi XE6(以及所有其他类似的 Delphi 最新版本)使添加清单变得容易,在项目选项中,我已经这样做了。
这是我使用 MSDN 资源确定的 .manifest 内容。我怀疑它可能有点不正确。
如果您想尝试此清单,请创建一个空的 VCL 应用程序,将此内容用作您的清单,然后添加代码(代码目前附在我对这个问题的回答中)。
<?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>
有人让这个工作吗?我发现以上内容无法识别。如果我先调用SetProcessDPIAwareness(Process_Per_Monitor_DPI_Aware),然后再调用GetProcessDPIAwareness(hProc,Awareness),我会得到必要的Awareness = Process_Per_Monitor_DPI_Aware,但我已经读到这种方法有潜在的缺点,所以我更喜欢一种有效的Manifest-only方法。
如果我打电话给GetProcessDPIAwareness(hProc,Awareness),我会返回“Awareness = Process_DPI_Unaware”。
我的另一个担心是,在 MSDN 来源中,他们指定添加附加清单。然而,我正在使用 Delphi XE6 的 IDE 将一个和唯一一个清单链接到我的应用程序中的能力。我从来没有注意到添加任何额外的清单而不是只有一个清单是一个问题,除了可能 Visual Studio 2010 中的 .manifest 管理系统是蹩脚的,这就是为什么存在提示,因此与其他 IDE 无关/语言。
在 Visual Studio 2013 中,项目选项中有一个复选框,但我没有 Visual Studio 2013,因此无法检查有效的 .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>
上面的迷你清单改变了应用程序的行为,但不完全是我想要的方式。通过上述微型清单,可以检测到旧的 Windows 8.0/Windows 7/Vista DPI 感知级别。
更新 2:
感谢雷米的想法。有趣的是,以下内容似乎足以允许应用程序启动。但是,将 SMI/2005 语法与上述混合会导致并行启动错误。你可以看到微软一直在大量修改他们的清单。请注意,以下内容实际上并不能解决我的问题,但它提供了另一种可能接近实际解决方案的“潜在基本形式”:
<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>
更新 3:
CODE RED ALERT! 不要在任何 Delphi VCL 应用程序中使用以下 OS COMPATIBILITY 标志:
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>。微软以我什至无法猜测的可怕方式破坏了鼠标捕获行为,破坏了窗口绘画。打开此标志会在我的应用程序中引起非常细微的错误,包括绘制问题、无法单击控件(由于鼠标捕获丢失,鼠标按下消息未到达控件)以及许多其他问题。
【问题讨论】:
-
添加了其他清单,例如通过 mt.exe 工具只是合并到一个清单中(允许在应用程序中),不是吗?我相信你应该只修改你的应用程序。表现出来而不试图拥有更多。
-
好的,很高兴知道。我怀疑我上面有一些模糊的 XML/Manifest 元数据。
-
我建议更改顶级 XML 元素的顺序。让
<dependency>成为第一个,然后是<compatibility>,最后是<application>。这些是在 Windows 中引入这些功能的顺序。 XML 不应该是顺序敏感的,但如果使用 XML 模式则可以。 Windows 的解析器可能对顺序敏感,它可能需要先查看 Win8.1 的<compatibility>元素,然后才能处理<dpiAware>元素。 -
另外,即使DPI-Aware documentation 表示
<WindowsSettings>元素的XML 命名空间是http://schemas.microsoft.com/SMI/2005/WindowsSettings,Application Manifests documentation 却表示命名空间是http://schemas.microsoft.com/SMI/2011/WindowsSettings,所以请尝试两者。跨度> -
我添加了我的代码,所以任何拥有 Windows 8.1 和 Delphi XE 的人都可以尝试一下。在您的主应用程序表单中,运行以下代码:
uses PerMonitorApi; ... SomeLabelControl.Visible := SystemCanSupportPerMonitorDpi( False);
标签: windows delphi windows-8.1 dpi delphi-xe6