下面我的代码应该显示每英寸N行。相反,我得到的每英寸多于N行。线之间的距离略小。此外,更改屏幕分辨率会使线条之间的距离也发生变化。有谁知道如何处理?
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace MyApp
{
class MyControl : Control
{
private readonly ContainerVisual container = new ContainerVisual();
private readonly DrawingVisual drawing = new DrawingVisual();
private void RenderDrawing()
{
var s = PresentationSource.FromVisual(this);
var dpiX = 96 * s.CompositionTarget.TransformToDevice.M11;
var dpiY = 96 * s.CompositionTarget.TransformToDevice.M22;
double N = 1;
using (var c = drawing.RenderOpen())
{
var p = new Pen(new SolidColorBrush(Colors.Black), 1);
for (int i = 0; i < 10; i++)
{
var x = i * dpiX / N;
c.DrawLine(p, new Point(x, 0), new Point(x, 100));
}
}
}
protected override Size ArrangeOverride(Size s)
{
RenderDrawing();
return s;
}
protected override Visual GetVisualChild(int index)
{
return container;
}
protected override Size MeasureOverride(Size s)
{
return new Size();
}
protected override int VisualChildrenCount
{
get { return 1; }
}
public MyControl()
{
container.Children.Add(drawing);
AddVisualChild(container);
}
}
}
答案 0 :(得分:1)
这篇文章似乎讨论了同样的问题:WPF DPI issues 除了要求用户设置与屏幕的物理DPI相对应的正确DPI设置之外,没有解决此问题的方法。我发现使生活更轻松的解决方法是使用WPF应用程序级别缩放,如下所述:http://www.odewit.net/ArticleContent.aspx?id=WpfDpiScaling&lang=en&format=html
答案 1 :(得分:0)
不确定这是否能实现您的目标,但如果问题与舍入有关,则应该会有所帮助。正如我在评论中所说,你的代码看起来大多是正确的,我认为这是dpi计算的一个舍入问题。由于您希望基于96 dpi进行渲染,请根据96dpi计算坐标,然后将点转换为您的设备。为了清晰起见,我写了更多内容,您可以使用单个数组点,只记得i
是起点,i+1
是终点,然后您只需要调用一次改变点。 p>
private void RenderDrawing()
{
var s = PresentationSource.FromVisual(this);
var dpiX = 96;
int numberOfLines = 10;
double N = 1;
double spacing = dpiX / N;
var startPoints = new Point[numberOfLines]();
var endPoints = new Point[numberOfLines]();
for (int i = 0; i < numberOfLines; i++)
{
var x = i * spacing;
startPoints[i] = new Point(x, 0);
endPoints[i] = new Point(x, 100);
}
s.CompositionTarget.TransformToDevice.Transform(startPoints);
s.CompositionTarget.TransformToDevice.Transform(endPoints);
using (var c = drawing.RenderOpen())
{
using (var p = new Pen(new SolidColorBrush(Colors.Black), 1))
{
for(int i=0; i < numberOfLines; i++)
{
c.DrawLine(p, startPoints[i], endPoints[i]);
}
}
}
}