美好的一天!
我一直工作在一个WPF应用程序有一段时间了(作为一个学习的经验哦男孩,这是一个学习的经验)和它终于准备发布。 发布意味着我的HTPC安装它在那里将被用来浏览我的电影收藏。
我设计我的电脑它运行1920×1080,但在正常的DPI设置上,而HTPC / TV是在相同的分辨率运行,但较高的DPI设置明显的原因。
问题是我的应用程序进入疯狂的HTPC,至于视觉去搞乱了几乎一切。 我知道这是由于糟糕的设计(过失),但由于它是只能由我使用我正在寻找一个快速解决方案,而不是一个完整的重新设计的应用程序。 我读它有可能被DPI意识到通过添加以下到AssemblyInfo.cs中停止应用程序:
[assembly: System.Windows.Media.DisableDpiAwareness]
然而,这似乎并没有产生任何影响和应用程序的行为保持不变。
任何人都可以点我在正确的方向?
谢谢你,约翰
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
,并从该计算,仅仅是撤消缩放和使用,在一个新的矩阵LayoutTransform
或RenderTransform
。
使用方法(甚至把它放在一个转换器)来修改一个明确的基础上DIP(与设备无关的位置)位置/长度....你可以做,如果你希望你的窗口大小以一个特定的像素大小相匹配。
本博客文章介绍了如何使用装饰的子类来做到这一点。
总之,创建这样一个类:
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>
以上都不是真正禁用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);
速战速决将只是包裹在你的窗口的内容Viewbox控件 。 如果视框的直接孩子有一个明确的宽度和高度,如果长宽比为在两台机器上是相同的,那么这应该让你和几乎立即运行。
DpiAwareness
只影响DPI虚拟化。 在Windows中,它显示为“使用Windows XP样式缩放”在Windows 7及8个自定义分辨率对话框,在其中选中启用意味着禁用和未选中的手段。 (请记住,申请的主要字体大小屏幕上,如果你改变它!OK'ing盒子是不够的。)
如果你有DPI虚拟化被关闭,那么它使零差价你的应用程序告诉它支持的操作系统,它总是使用标准的缩放。 当它的上,它使之间的真正比例(知道),只是拍打在整个应用程序(不知道)双线性缩放的差异。
我只记得另一个警告,DPI的virt不会在所有无Aero Glass的工作工作。
对于使用VB.NET那些访问app.manifest的方法是:
然后去掉这一部分,将其设置为“假”
克林Pirtea的回答确实禁用DPI缩放。
对于那些谁想要舒展的显示比例超过100%的应用程序,并接受模糊,卡洛斯博劳的回答工作。 下面是针对.NET 4.6(C#)的方式:
1清单文件添加到您的应用程序项目
- 右击项目,添加 - >新建项目
- 选择常规 - >应用程序清单文件
2取消注释下面并设置dpiAware =假:
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware>
</windowsSettings>
</application>