禁用WPF应用程序DPI意识(Disable DPI awareness for WPF appli

2019-07-05 04:11发布

美好的一天!

我一直工作在一个WPF应用程序有一段时间了(作为一个学习的经验哦男孩,这是一个学习的经验)和它终于准备发布。 发布意味着我的HTPC安装它在那里将被用来浏览我的电影收藏。

我设计我的电脑它运行1920×1080,但在正常的DPI设置上,而HTPC / TV是在相同的分辨率运行,但较高的DPI设置明显的原因。

问题是我的应用程序进入疯狂的HTPC,至于视觉去搞乱了几乎一切。 我知道这是由于糟糕的设计(过失),但由于它是只能由我使用我正在寻找一个快速解决方案,而不是一个完整的重新设计的应用程序。 我读它有可能被DPI意识到通过添加以下到AssemblyInfo.cs中停止应用程序:

[assembly: System.Windows.Media.DisableDpiAwareness]

然而,这似乎并没有产生任何影响和应用程序的行为保持不变。

任何人都可以点我在正确的方向?

谢谢你,约翰

Answer 1:

DPIAwareness

只是一些想法(没试过):

你在XP上运行? 这选项可能无法在该平台上工作。

  • http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/5e60a54d-baf5-46e3-9eac-a959f2a0fba1/

接下来是可能只是不同的方式来设置相同DpiAwareness选项:

  • 看看你的EXE的“兼容模式”设置...右键点击它的属性...,打开“禁用显示缩放”

  • 创建一个清单,然后说你不知道

     <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > ... <asmv3:application> <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> <dpiAware>false</dpiAware> </asmv3:windowsSettings> </asmv3:application> ... </assembly> 
  • 调用SetProcessDPIAware (认为你必须在创建窗口之前调用这个早期即)

    http://msdn.microsoft.com/en-gb/library/windows/desktop/ms633543(v=vs.85).aspx

您可以拨打IsProcessDPIAware来检查,如果你的应用程序已应用与否的设置。

找出DPI

这里是你如何找出DPI您正在使用的是什么:

访问CompositionTarget通过PresentationSource你的Window ,以找出DPI缩放它使用.....那么你可以使用这些值做一些缩放的调整,即缩小你的“东西”(其尺寸/长度/等都在设备规定独立单元),这样,当它放大由于较高的DPI实际上是它不会爆炸的物理像素利用率(......这可以通过各种方式来完成,例如ViewBox ,或宽度计算等等的元素) 。

double dpiX, double dpiY;
PresentationSource presentationsource = PresentationSource.FromVisual(mywindow);

if (presentationsource != null) // make sure it's connected
{
    dpiX = 96.0 * presentationsource.CompositionTarget.TransformToDevice.M11;
    dpiY = 96.0 * presentationsource.CompositionTarget.TransformToDevice.M22;
}
  • 如何在WPF大小转换为物理像素?
  • http://wpftutorial.net/DrawOnPhysicalDevicePixels.html

做缩放调整

  • 使用ViewBox

    看到这个答案我做之前,允许一个Canvas使用该被解释为“原生”像素不管什么DPI缩放位置。

    WPF液晶屏全高清

  • 访问TransFormToDevice的缩放矩阵CompositionTarget ,并从该计算,仅仅是撤消缩放和使用,在一个新的矩阵LayoutTransformRenderTransform

  • 使用方法(甚至把它放在一个转换器)来修改一个明确的基础上DIP(与设备无关的位置)位置/长度....你可以做,如果你希望你的窗口大小以一个特定的像素大小相匹配。



Answer 2:

本博客文章介绍了如何使用装饰的子类来做到这一点。

总之,创建这样一个类:

namespace MyNamespace
{
    public class DpiDecorator : Decorator
    {
        public DpiDecorator()
        {
            this.Loaded += (s, e) =>
            {
                Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
                ScaleTransform dpiTransform = new ScaleTransform(1 / m.M11, 1 / m.M22);
                if (dpiTransform.CanFreeze)
                    dpiTransform.Freeze();
                this.LayoutTransform = dpiTransform;
            };
        }
    };
};

然后添加类似xmlns:custom="clr-namespace:MyNamespace"到你的顶层窗口定义,然后附上您DPI独立的用户界面<custom:DpiDecorator> ... </custom:DpiDecorator>



Answer 3:

以上都不是真正禁用WPF的DPI缩放。

这是如何缩放DPI在.NET 4.6通过WPF计算:1)HwndTarget它是由所有的视觉效果用的CompositionTarget。 2)的UIElement其是用于视觉效果的基类,并且其中缩放计算结果DPI被存储的地方。

WPF可以确保全局缩放时计算一次第一视觉时准备。 这是由布尔上HwndTarget {私人静态布尔_setDpi =真}控制。 计算DPI后,_setDpi字段设置为false和DPI知道使用方法,像这样的代码快捷方式{如果(HwndTarget._setDpi!)回报;}

类似的事情发生的每一个的UIElement,其使用相同的模式{私人静态布尔_setDpi =真}允许计算第一次。

下一个检查来自ProcessDpiAwareness其可以是无,过程,或监视器。 为了从考虑到你需要设置ProcessDpiAwareness到进程(INT 1)个体监测停止WPF。

最后,当计算DPI结果存储在2所列出呼吁的UIElement DpiScaleXValues和DpiScaleYValues。 所以,你需要这些初始化到正确的值。

下面是我用我自己(仅适用于.NET 4.6)的样本代码:

        var setDpiHwnd = typeof(HwndTarget).GetField("_setDpi", BindingFlags.Static | BindingFlags.NonPublic);
        setDpiHwnd?.SetValue(null, false);

        var setProcessDpiAwareness = typeof(HwndTarget).GetProperty("ProcessDpiAwareness", BindingFlags.Static | BindingFlags.NonPublic);
        setProcessDpiAwareness?.SetValue(null, 1, null);

        var setDpi = typeof(UIElement).GetField("_setDpi", BindingFlags.Static | BindingFlags.NonPublic);

        setDpi?.SetValue(null, false);

        var setDpiXValues = (List<double>)typeof(UIElement).GetField("DpiScaleXValues", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);

        setDpiXValues?.Insert(0, 1);

        var setDpiYValues = (List<double>)typeof(UIElement).GetField("DpiScaleYValues", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);

        setDpiYValues?.Insert(0, 1);


Answer 4:

速战速决将只是包裹在你的窗口的内容Viewbox控件 。 如果视框的直接孩子有一个明确的宽度和高度,如果长宽比为在两台机器上是相同的,那么这应该让你和几乎立即运行。



Answer 5:

DpiAwareness只影响DPI虚拟化。 在Windows中,它显示为“使用Windows XP样式缩放”在Windows 7及8个自定义分辨率对话框,在其中选中启用意味着禁用和未选中的手段。 (请记住,申请的主要字体大小屏幕上,如果你改变它!OK'ing盒子是不够的。)

如果你有DPI虚拟化被关闭,那么它使零差价你的应用程序告诉它支持的操作系统,它总是使用标准的缩放。 当它的上,它使之间的真正比例(知道),只是拍打在整个应用程序(不知道)双线性缩放的差异。

我只记得另一个警告,DPI的virt不会在所有无Aero Glass的工作工作。



Answer 6:

对于使用VB.NET那些访问app.manifest的方法是:

然后去掉这一部分,将其设置为“假”



Answer 7:

克林Pirtea的回答确实禁用DPI缩放。

对于那些谁想要舒展的显示比例超过100%的应用程序,并接受模糊,卡洛斯博劳的回答工作。 下面是针对.NET 4.6(C#)的方式:

1清单文件添加到您的应用程序项目

  1. 右击项目,添加 - >新建项目
  2. 选择常规 - >应用程序清单文件

2取消注释下面并设置dpiAware =假:

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


文章来源: Disable DPI awareness for WPF application
标签: wpf scaling dpi