0

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

2 回答 2

1

这篇文章似乎讨论了同样的问题:WPF DPI issues 除了要求用户设置与屏幕物理 DPI 对应的正确 DPI 设置外,没有解决此问题的方法。我发现使生活更轻松的一种解决方法是使用 WPF 应用程序级别缩放,如下所述:http ://www.odewit.net/ArticleContent.aspx?id=WpfDpiScaling&lang=en&format=html

于 2010-11-23T02:29:14.833 回答
0

不确定这是否会完成您正在寻找的内容,但如果问题与四舍五入有关,它应该会有所帮助。正如我在评论中所说,您的代码看起来大部分是正确的,我认为这是 dpi 计算的舍入问题。由于您希望基于 96 dpi 进行渲染,请根据 96 dpi 计算坐标,然后将这些点转换为您的设备。为了清楚起见,我写了更多,您可以使用单个点数组,只需记住这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]);
                 }
            }
        }
    }
于 2010-11-22T20:18:27.687 回答