SetProcessDpiAwareness not having effect

本文关键字:effect having not SetProcessDpiAwareness | 更新日期: 2023-09-27 18:09:24

我一直在尝试禁用ClickOnce应用程序的DPI感知。
我很快发现,不可能在清单中指定它,因为ClickOnce不支持asm。

我发现下一个选项是调用新的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 set: True
Process_System_DPI_Aware
设置DPI错误:System.ComponentModel。Win32Exception (0x80004005): Access is denied
System.ComponentModel。Win32Exception (0x80004005): The operation completed successfully

为什么应用程序仍然设置为DPI_Aware?这个电话是不是还不够早?
应用程序确实经历了DPI缩放。

当我使用manifest定义时:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
  </windowsSettings>
</application>

它确实返回process_dpi_unknown .

编辑1:
现在直接在pInvoke方法之后抓取Marshal.GetLastWin32Error(),这现在实际上返回了一个错误。

SetProcessDpiAwareness not having effect

注意SetLastErrorGetLastWin32Error,在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 (permonitorawarewpfwindows .xaml.cs中的注释)