• WPF 如何画出1像素的线


    如何有人告诉你,请你画出1像素的线,是不是觉得很简单,实际上在 WPF 上还是比较难的。

    本文告诉大家,如何让画出的线不模糊

    画出线的第一个方法,创建一个 Canvas ,添加一个线

    界面代码

                <Canvas x:Name="Canvas"></Canvas>
    

    在后台添加一条线

                Line myLine = new Line();
    
                myLine.Stroke = System.Windows.Media.Brushes.Black;
    
                myLine.X1 = 100;
                myLine.X2 = 200;  // 150 too far
                myLine.Y1 = 200;
                myLine.Y2 = 200;
    
                myLine.StrokeThickness = 1;
    
                Canvas.Children.Add(myLine);

    那么如何看到线模糊呢?

    简单方法是使用 ViewBox 和放大镜,可以看到模糊

    在界面添加下面代码

        <Viewbox >
                <Canvas x:Name="Canvas"></Canvas>
        </Viewbox>

    这时拖动窗口可以看到线放大

    可以看到线是模糊的,如果想要让线不模糊,可以添加下面的代码

            myLine.SnapsToDevicePixels = true;
                myLine.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);

    这个方法是从 [https://stackoverflow.com/q/2879033/6116637][https://stackoverflow.com/q/2879033/6116637]得到,但是无法对于自己的控件

    如果自己创建一个控件,那么直接使用 dc.DrawLine 得到不是清晰的

    创建一个类自定义控件,添加下面的代码画出线

            protected override void OnRender(DrawingContext dc)
            {
    
                    dc.DrawLine(_pen,  new Point(10, 10), new Point(310, 10));
    
            }

    可以看到,画出来的线是模糊的,于是看了微软的代码

    看了他的矩形是如何画的,看到他画出来的是清晰的,但是复制他的代码到我的控件,画出来不是清晰的

            /// <summary>
            /// Render callback.
            /// </summary>
            protected override void OnRender(DrawingContext drawingContext)
            {
                Pen pen = GetPen();
                drawingContext.DrawRoundedRectangle(Fill, pen, _rect, RadiusX, RadiusY);
            }

    下面代码是我复制他的,但是自己的控件画出来在放大时,线模糊,所以直接复制是无法做到wr的矩形那样

           protected override void OnRender(DrawingContext dc)
            {
    
                dc.DrawRoundedRectangle(null, _pen, new Rect(new Point(10, 10), new Size(100, 100)), 5, 5);
            }

    在界面画出来wr 的矩形和自定义控件,可以看到,微软的是清晰的

    那么是不是wr 做了特殊的东西,到现在还不知道,但是找到了一个方法,可以画出清晰

    缩小看到的图片是这样

    那么放大时就是下面这张图

    所以需要在放大时,也画一个像素,
    这个方法就是本文,所以这是在翻译,只是没有使用对所有的文字翻译,来自工藤大神的方法。

    本文使用的方法很简单,第一步

    复制方法到一个静态类

        public static void DrawSnappedLinesBetweenPoints(this DrawingContext dc,
            Pen pen, double lineThickness, params Point[] points)
        {
            var guidelineSet = new GuidelineSet();
            foreach (var point in points)
            {
                guidelineSet.GuidelinesX.Add(point.X);
                guidelineSet.GuidelinesY.Add(point.Y);
            }
            var half = lineThickness / 2;
            points = points.Select(p => new Point(p.X + half, p.Y + half)).ToArray();
            dc.PushGuidelineSet(guidelineSet);
            for (var i = 0; i < points.Length - 1; i = i + 2)
            {
                dc.DrawLine(pen, points[i], points[i + 1]);
            }
            dc.Pop();
        }

    然后就可以在自定义控件使用下面的代码

          protected override void OnRender(DrawingContext dc)
            {
                dc.DrawSnappedLinesBetweenPoints(_pen,1, new[]
                {
                    new Point(10, 10),
                    new Point(310, 10),
                });
            }

    可以看到线是清晰的

    参见:https://stackoverflow.com/a/45189552/6116637

    http://www.nbdtech.com/Blog/archive/2008/11/20/blurred-images-in-wpf.aspx

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

  • 相关阅读:
    java面试之String源码中equals具体实现
    JVM虚拟机—JVM的垃圾回收机制(转载)
    Mysql学习笔记—视图
    Mysql学习笔记—索引
    JVM虚拟机—JVM内存
    设计模式—装饰器模式
    设计模式—代理模式
    设计模式—适配器模式
    设计模式—观察者模式
    设计模式—建造者模式
  • 原文地址:https://www.cnblogs.com/lindexi/p/12087359.html
Copyright © 2020-2023  润新知