如何每英寸画出N行?

时间:2010-11-22 19:12:20

标签: wpf dpi

下面我的代码应该显示每英寸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);
        }
    }
}

2 个答案:

答案 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是终点,然后您只需要调用一次改变点。

    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]);
                 }
            }
        }
    }