WPF使用DrawingContext实现绘制刻度条

WPF 使用 DrawingContext 绘制刻度条

  • 框架使用大于等于.NET40
  • Visual Studio 2022;
  • 项目使用 MIT 开源许可协议;
  • 定义Interval步长、SpanInterval间隔步长、MiddleMask中间步长。
  • 当步长/ 间隔步长= 需要绘制的小刻度。
  • 循环绘制小刻度,判断当前j并取中间步长的模,如果模!=零就绘制中高线。
  • StartValue 开始绘制刻度到EndValue 结束刻度。
  • CurrentGeometry 重新绘制当前刻度的Path值。
  • CurrentValue 当前值如果发生变化时则去重新CurrentGeometry 。

1) 准备Ruler.cs如下:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WPFDevelopers.Controls
{
    public class Ruler : Control
    {
        public static readonly DependencyProperty IntervalProperty =
            DependencyProperty.Register("Interval", typeof(double), typeof(Ruler), new UIPropertyMetadata(30.0));

        public static readonly DependencyProperty SpanIntervalProperty =
            DependencyProperty.Register("SpanInterval", typeof(double), typeof(Ruler), new UIPropertyMetadata(5.0));

        public static readonly DependencyProperty MiddleMaskProperty =
            DependencyProperty.Register("MiddleMask", typeof(int), typeof(Ruler), new UIPropertyMetadata(2));

        public static readonly DependencyProperty CurrentValueProperty =
            DependencyProperty.Register("CurrentValue", typeof(double), typeof(Ruler),
                new UIPropertyMetadata(OnCurrentValueChanged));

        public static readonly DependencyProperty StartValueProperty =
            DependencyProperty.Register("StartValue", typeof(double), typeof(Ruler), new UIPropertyMetadata(120.0));

        public static readonly DependencyProperty EndValueProperty =
            DependencyProperty.Register("EndValue", typeof(double), typeof(Ruler), new UIPropertyMetadata(240.0));

        public static readonly DependencyProperty CurrentGeometryProperty =
            DependencyProperty.Register("CurrentGeometry", typeof(Geometry), typeof(Ruler),
                new PropertyMetadata(Geometry.Parse("M 257,0 257,25 264,49 250,49 257,25")));

        static Ruler()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Ruler), new FrameworkPropertyMetadata(typeof(Ruler)));
        }

        public Ruler()
        {
            Loaded += Ruler_Loaded;
        }

        public double Interval
        {
            get => (double)GetValue(IntervalProperty);

            set => SetValue(IntervalProperty, value);
        }

        public double SpanInterval
        {
            get => (double)GetValue(SpanIntervalProperty);

            set => SetValue(SpanIntervalProperty, value);
        }

        public int MiddleMask
        {
            get => (int)GetValue(MiddleMaskProperty);

            set => SetValue(MiddleMaskProperty, value);
        }

        public double CurrentValue
        {
            get => (double)GetValue(CurrentValueProperty);

            set
            {
                SetValue(CurrentValueProperty, value);
                PaintPath();
            }
        }

        public double StartValue
        {
            get => (double)GetValue(StartValueProperty);

            set => SetValue(StartValueProperty, value);
        }

        public double EndValue
        {
            get => (double)GetValue(EndValueProperty);

            set => SetValue(EndValueProperty, value);
        }

        public Geometry CurrentGeometry
        {
            get => (Geometry)GetValue(CurrentGeometryProperty);

            set => SetValue(CurrentGeometryProperty, value);
        }

        private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ruler = d as Ruler;
            ruler.CurrentValue = Convert.ToDouble(e.NewValue);
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
            var nextLineValue = 0d;
            var one_Width = ActualWidth / ((EndValue - StartValue) / Interval);

            for (var i = 0; i <= (EndValue - StartValue) / Interval; i++)
            {
                var numberText = DrawingContextHelper.GetFormattedText((StartValue + i * Interval).ToString(),
                    (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#FFFFFF"), FlowDirection.LeftToRight,
                    10);
                drawingContext.DrawText(numberText, new Point(i * one_Width - 8, 0));
                drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.White), 1), new Point(i * one_Width, 25),
                    new Point(i * one_Width, ActualHeight - 2));
                var cnt = Interval / SpanInterval;
                for (var j = 1; j <= cnt; j++)
                    if (j % MiddleMask == 0)
                        drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.White), 1),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 2),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 10));
                    else
                        drawingContext.DrawLine(new Pen(new SolidColorBrush(Colors.White), 1),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 2),
                            new Point(j * (one_Width / cnt) + nextLineValue, ActualHeight - 5));

                nextLineValue = i * one_Width;
            }
        }

        private void Ruler_Loaded(object sender, RoutedEventArgs e)
        {
            PaintPath();
        }

        private void PaintPath()
        {
            var d_Value = CurrentValue - StartValue;
            var one_Value = ActualWidth / (EndValue - StartValue);
            var x_Point = one_Value * d_Value + ((double)Parent.GetValue(ActualWidthProperty) - ActualWidth) / 2d;
            CurrentGeometry =
                Geometry.Parse($"M {x_Point},0 {x_Point},25 {x_Point + 7},49 {x_Point - 7},49 {x_Point},25");
        }
    }
}

2) 使用RulerControlExample.xaml.cs如下:

<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.RulerControlExample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
             xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Slider x:Name="PART_Slider" IsSnapToTickEnabled="True"
                Value="40"
                Minimum="10"
                Maximum="210"/>
        <UniformGrid Rows="3">
            <Grid Background="{StaticResource CircularDualSolidColorBrush}" Height="51" Margin="40,0">
                <Path Stroke="{StaticResource SuccessPressedSolidColorBrush}" StrokeThickness="1" Fill="{StaticResource SuccessPressedSolidColorBrush}"
                  Data="{Binding ElementName=PART_Ruler, Path=CurrentGeometry,Mode=TwoWay}" />
                <wpfdev:Ruler x:Name="PART_Ruler" Margin="40,0" Interval="20" StartValue="10" EndValue="210"
                          CurrentValue="{Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
            </Grid>
            <Grid Background="{StaticResource DangerPressedSolidColorBrush}" Height="51" Margin="40,0">
                <Path Stroke="{StaticResource SuccessPressedSolidColorBrush}" StrokeThickness="1" Fill="{StaticResource SuccessPressedSolidColorBrush}"
                  Data="{Binding ElementName=PART_Ruler1, Path=CurrentGeometry,Mode=TwoWay}" />
                <wpfdev:Ruler x:Name="PART_Ruler1" Margin="40,0" Interval="20" StartValue="10" EndValue="210"
                          CurrentValue="{Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
            </Grid>
            <Grid Background="{StaticResource WarningPressedSolidColorBrush}" Height="51" Margin="40,0">
                <Path Stroke="{StaticResource SuccessPressedSolidColorBrush}" StrokeThickness="1" Fill="{StaticResource SuccessPressedSolidColorBrush}"
                  Data="{Binding ElementName=PART_Ruler2, Path=CurrentGeometry,Mode=TwoWay}" />
                <wpfdev:Ruler x:Name="PART_Ruler2" Margin="40,0" Interval="20" StartValue="10" EndValue="210"
                          CurrentValue="{Binding ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
            </Grid>
        </UniformGrid>
        
        
    </Grid>
</UserControl>

以上就是WPF使用DrawingContext实现绘制刻度条的详细内容,更多关于WPF刻度条的资料请关注我们其它相关文章!

(0)

相关推荐

  • 基于WPF实现弹幕效果的示例代码

    WPF 实现弹幕效果 框架使用大于等于.NET40: Visual Studio 2022; 项目使用 MIT 开源许可协议: 此篇代码目的只是为了分享思路 实现基础弹幕一定是要使用Canvas比较简单,只需实现Left动画从右到左. 弹幕消息使用Border做弹幕背景. 内容使用TextBlock做消息文本展示. 当动画执行完成默认移除Canvas中的弹幕控件. 使用这种方式去加载弹幕GPU会占较高. 1) 准备BarrageExample.xaml如下: <UserControl x:Cla

  • WPF使用DrawingContext实现二维绘图

    DrawingContext比较类似WinForm中的Graphics 类,是基础的绘图对象,用于绘制各种图形,它主要API有如下几种: 绘图API 绘图API一般形为DrawingXXX系列,常用的基础的绘图API有: DrawEllipse DrawGeometry DrawGlyphRun DrawImage DrawRectangle DrawRoundedRectangle 这些和GDI的API是非常相似的,WPF的API中另外还都有一个带动画的版本,不过一般很少用. 另外还有两个相对

  • WPF使用Geometry绘制几何图形

    在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常应用中,更多的是使用DrawGeometry函数,它可以绘制更多复杂的几何图形,并且提供了许多强大而易用的函数,在大多数场景下,甚至可以取代DrawEllipse和DrawRectangle函数. 在WPF图形体系中,Geometry类表示几何图形的基类,使用的时候是实例化它的一些子类,具体的有: 基本几何图形 线段:LineG

  • WPF实现绘制统计图(柱状图)的方法详解

    目录 前言 实现代码 效果预览 前言 有小伙伴提出需要实现统计图. 由于在WPF中没有现成的统计图控件,所以我们自己实现一个. PS:有更好的方式欢迎推荐. 实现代码 一.创建 BasicBarChart.cs 继承 Control代码如下. BasicBarChart.cs实现思路如下 1.SeriesArray :存放展示集合 . 2.重写OnRender . 3.先绘制X轴线. 4.调用GetFormattedText()绘制底部类别. 5.调用GetFormattedText()绘制左侧

  • WPF使用DrawingContext实现绘制刻度条

    WPF 使用 DrawingContext 绘制刻度条 框架使用大于等于.NET40: Visual Studio 2022; 项目使用 MIT 开源许可协议: 定义Interval步长.SpanInterval间隔步长.MiddleMask中间步长. 当步长/ 间隔步长= 需要绘制的小刻度. 循环绘制小刻度,判断当前j并取中间步长的模,如果模!=零就绘制中高线. 从StartValue 开始绘制刻度到EndValue 结束刻度. CurrentGeometry 重新绘制当前刻度的Path值.

  • WPF基于物理像素绘制图形

    WPF中有一个DrawingContext类,该类提供了很多画法方法,例如DrawLine,DrawText,DrawRectangle等.开发者使用它们可以方便地进行图形绘制.不过,在使用DrawingContext过程中,我发现使用DawLine方法画出的线条在某些部分有些模糊.这个问题的解决,需要一些计算机图形学方面的知识,使用的方法并不是很复杂.不过,这个方法所涉及到的一些过程有些令人费解(好吧,我没有专门学过计算机图形学),本文是我在实践中的一些尝试和经验的总结. 还是从一个例子开始吧

  • php绘制一条弧线的方法

    本文实例讲述了php绘制一条弧线的方法.分享给大家供大家参考.具体如下: 弧线相当于截取了椭圆的一部分.代码如下: 复制代码 代码如下: <?php //1.创建画布 $im = imagecreatetruecolor(300,200);//新建一个真彩色图像,默认背景是黑色,返回图像标识符.另外还有一个函数 imagecreate 已经不推荐使用. //2.绘制所需要的图像 $red = imagecolorallocate($im,255,0,0);//创建一个颜色,以供使用 imagea

  • php绘制一条直线的方法

    本文实例讲述了php绘制一条直线的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <?php //1.创建画布 $im = imagecreatetruecolor(300,200);//新建一个真彩色图像,默认背景是黑色,返回图像标识符.另外还有一个函数 imagecreate 已经不推荐使用. //2.绘制所需要的图像 $red = imagecolorallocate($im,255,0,0);//创建一个颜色,以供使用 imageline($im,30,30,240

  • Android LineChart绘制多条曲线的方法

    本文实例为大家分享了Android LineChart绘制多条曲线的具体代码,供大家参考,具体内容如下 目标效果: 1.新建custom_marker_view.xml页面作为点击弹出框的页面: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" andr

  • python使用matplotlib模块绘制多条折线图、散点图

    今天想直观的展示一下数据就用到了matplotlib模块,之前都是一张图只有一条曲线,现在想同一个图片上绘制多条曲线来对比,实现很简单,具体如下: #!usr/bin/env python #encoding:utf-8 ''' __Author__:沂水寒城 功能:折线图.散点图测试 ''' import random import matplotlib import matplotlib.pyplot as plt def list2mat(data_list,w): ''' 切片.转置 '

  • unity绘制一条流动的弧线(贝塞尔线)

    本文实例为大家分享了unity绘制一条流动弧线的具体代码,供大家参考,具体内容如下 最终效果 把下面脚本复制,直接拖上脚本,设置两个点(物体)的位置 GameObject1是开始点的位置,GameObject2是结束点的位置 public Transform[] controlPoints; public LineRenderer lineRenderer; public float centerPoint =0.1f; private int layerOrder = 0; //生成弧线中间的

  • js绘制一条直线并旋转45度

    本文实例为大家分享了js绘制一条直线并旋转45度的具体代码,供大家参考,具体内容如下 绘制一条直线,并旋转45度 html 页面 <canvas id="canvas" width="300" height="300" style="background-color: orange;"></canvas> js页面 <script> var canvas = document.getElem

  • C#动态绘制多条曲线的方法

    本文实例为大家分享了C#动态绘制多条曲线的具体代码,供大家参考,具体内容如下 实时绘制多条曲线,纵轴为数值,横轴为时间,精确到毫秒 实现效果如下: 代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Thr

随机推荐