如何每英寸画N条线?

发布于 2024-10-04 00:23:48 字数 1621 浏览 7 评论 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);
        }
    }
}

my code below is supposed to display N lines per inch. instead i get a little more than N lines per inch. the distance between lines is somewhat smaller. in addition, changing the screen resolution makes the distance between lines change too. does anyone know how to handle that?


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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

開玄 2024-10-11 00:23:48

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

this article seems to discuss the same problem: WPF DPI issues
there is no solution to this problem other than asking the user to set the correct DPI settings that correspond to the physical DPI of the screen. a workaround that i found that makes life a little easier is to use WPF application level scaling as described here: http://www.odewit.net/ArticleContent.aspx?id=WpfDpiScaling&lang=en&format=html

装纯掩盖桑 2024-10-11 00:23:48

不确定这是否能实现您想要的效果,但如果问题与舍入有关,它应该会有所帮助。正如我在评论中所说,您的代码看起来大部分是正确的,我认为这是 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]);
                 }
            }
        }
    }

Not sure if this would accomplish what you are looking for, but it should help if the issue has to do with rounding. As I said in comments, your code looks mostly correct, I think it is a rounding issue with the dpi computation. Since you are desiring to render based on 96 dpi, compute the coordinates based on 96dpi and then convert the points to your device. I wrote this more for clarity, you could use a single array of points and just remember that i is the start point and i+1 is the end point and then you would only have to make a single call to transform the points.

    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]);
                 }
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文