SetProcessDpiAwareness无效

时间:2015-08-21 19:41:45

标签: c# wpf pinvoke clickonce dpi

我一直在尝试在ClickOnce应用程序上禁用DPI感知 我很快发现,无法在清单中指定它,因为ClickOnce不支持清单文件中的asm.v3。

我找到的下一个选项是调用新的Windows函数SetProcessDpiAwareness

根据this教程,

  

在创建应用程序窗口之前调用SetProcessDpiAwareness。

this教程,

  

您必须在任何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):访问被拒绝
  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。

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

1 个答案:

答案 0 :(得分:9)

请注意SetLastErrorGetLastWin32ErrorMessageBox.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中的评论)