SetProcessDpiAwareness没有效果
我一直在尝试在ClickOnce应用程序上禁用DPI感知。
我很快发现,无法在清单中指定它,因为ClickOnce不支持清单文件中的asm.v3。
我找到的下一个选项是调用新的Windows函数SetProcessDpiAwareness 。
根据这个教程,
在创建应用程序窗口之前调用SetProcessDpiAwareness。
这个教程,
您必须在任何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设置:True
Process_System_DPI_Aware
设置DPI错误:System.ComponentModel.Win32Exception(0x80004005):拒绝访问
System.ComponentModel.Win32Exception(0x80004005):操作成功完成
为什么应用程序仍设置为DPI_Aware? 这个电话不够早吗?
该应用程序确实经历了DPI扩展。
当我使用清单定义时:
false
它确实返回Process_DPI_Unaware。
编辑1:
现在,在pInvoke方法之后直接获取Marshal.GetLastWin32Error(),现在实际上会返回错误。
请注意SetLastError
和GetLastWin32Error
, MessageBox.Show
之间的任何调用都会影响其结果。 确保在调用本机方法后始终获得最后一个错误。
因此,您可能会很好地获得预期的行为,但却被错误代码误导了。
有关完整说明,请参阅此博客文章: http : //blogs.msdn.com/b/oldnewthing/archive/2015/08/19/10636096.aspx
编辑
不太确定导致拒绝访问的原因……但是有一个简单而有效的技巧可以禁用DPI感知:
编辑AssemblyInfo.cs并添加以下内容:
[assembly: DisableDpiAwareness]
来源: https ://code.msdn.microsoft.com/windowsdesktop/Per-Monitor-Aware-WPF-e43cde33(PerMonitorAwareWPFWindow.xaml.cs中的评论)