我一直在尝试禁用 ClickOnce 应用程序上的 DPI 感知。
我很快发现,不可能在清单中指定它,因为 ClickOnce 不支持清单文件中的 asm.v3。
我发现的下一个选项是调用新的 Windows 函数设置进程Dpi感知 https://msdn.microsoft.com/en-us/library/windows/desktop/dn302122(v=vs.85).aspx.
根据this https://msdn.microsoft.com/en-us/library/windows/desktop/dd464659(v=vs.85).aspx教程,
在创建应用程序窗口之前调用 SetProcessDpiAwareness。
And this https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).aspx教程,
您必须在任何 Win32API 调用之前调用 SetProcessDpiAwareness
您必须尽早调用该函数。因此,为了进行测试,我创建了一个完全空白的 WPF 应用程序,并将其作为我的整个 App 类:
[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());
}
3个消息框显示以下内容:
Dpi 设置:真
Process_System_DPI_Aware
设置 DPI 错误:System.ComponentModel.Win32Exception (0x80004005):访问被拒绝
System.ComponentModel.Win32Exception(0x80004005):操作成功完成
为什么应用程序仍设置为 DPI_Aware?这个电话还不够早吗?
该应用程序确实经历了 DPI 缩放。
当我使用清单定义时:
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
</windowsSettings>
</application>
它确实返回 Process_DPI_Unaware。
EDIT 1:
现在直接在 pInvoke 方法之后获取 Marshal.GetLastWin32Error() ,这实际上会返回一个错误。