wpf SetProcessDpiAwareness 没有效果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32148151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:21:20  来源:igfitidea点击:

SetProcessDpiAwareness not having effect

c#wpfpinvokeclickoncedpi

提问by René Sackers

I've been trying to disable the DPI awareness on a ClickOnce application.
I quickly found out, it is not possible to specify it in the manifest, because ClickOnce does not support asm.v3 in the manifest file.

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

The next option I found was calling the new Windows function SetProcessDpiAwareness.

我发现的下一个选项是调用新的 Windows 函数SetProcessDpiAwareness

According to thistutorial,

根据教程,

Call SetProcessDpiAwareness before you create the application window.

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

And thistutorial,

这个教程,

you must call SetProcessDpiAwareness prior to any Win32API call

您必须在任何 Win32API 调用之前调用 SetProcessDpiAwareness

You have to call the function pretty early on. So, to test, I have created an entirely blank WPF application, and made this my entire App class:

您必须很早就调用该函数。因此,为了进行测试,我创建了一个完全空白的 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());
}

The 3 message boxes show this content:

3 个消息框显示以下内容:

Dpi set: True
Process_System_DPI_Aware
Set DPI error: System.ComponentModel.Win32Exception (0x80004005): Access is denied
System.ComponentModel.Win32Exception (0x80004005): The operation completed successfully

Dpi 设置:True
Process_System_DPI_Aware
设置 DPI 错误:System.ComponentModel.Win32Exception (0x80004005):访问被拒绝
System.ComponentModel.Win32Exception (0x80004005):操作成功完成

Why is the application still set to DPI_Aware? Is this call not early enough?
The application does indeed experience DPI scaling.

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

When I use the manifest definition:

当我使用清单定义时:

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

It does return Process_DPI_Unaware.

它确实返回 Process_DPI_Unaware。

EDIT 1:
Now grabbing Marshal.GetLastWin32Error() directly after pInvoke methods, this now actually returns an error.

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

采纳答案by Aybe

Beware with SetLastErrorand GetLastWin32Error, any call in between such as MessageBox.Showwill affect its result. Make sure to always get the last error right after calling your native method.

小心SetLastErrorGetLastWin32Error,任何介于两者之间的调用MessageBox.Show都会影响其结果。确保始终在调用本机方法后立即获得最后一个错误。

So it could be very well that you are getting the expected behavior but being misled by the error code.

所以很可能你得到了预期的行为,但被错误代码误导了。

See this blog post for a complete explanation : http://blogs.msdn.com/b/oldnewthing/archive/2015/08/19/10636096.aspx

有关完整说明,请参阅此博客文章:http: //blogs.msdn.com/b/oldnewthing/archive/2015/08/19/10636096.aspx

EDIT

编辑

Not quite sure about what's causing access denied ...but there's a simple and effective trick that disables DPI awareness :

不太确定是什么导致访问被拒绝......但是有一个简单而有效的技巧可以禁用 DPI 感知:

Edit your AssemblyInfo.csand add the following:

编辑您的AssemblyInfo.cs并添加以下内容:

[assembly: DisableDpiAwareness]

Source: https://code.msdn.microsoft.com/windowsdesktop/Per-Monitor-Aware-WPF-e43cde33(comments in PerMonitorAwareWPFWindow.xaml.cs)

来源:https: //code.msdn.microsoft.com/windowsdesktop/Per-Monitor-Aware-WPF-e43cde33(PerMonitorAwareWPFWindow.xaml.cs 中的评论)