簡體   English   中英

繪制具有不同顏色端蓋的WPF線

[英]Draw a WPF Line With Different Colored End Caps

WPF新手。 我需要繪制一條線(在網格“單元格”內部,如果有所不同),它的開始/結束上限與行本身顏色不同。 似乎在線上獲得上限很容易; 讓它成為一種不同的顏色並不是那么簡單。

我已經回顧了Line,PolyLine,Pen,Path,LineGeometry和EllipseGeometry對象。 所有這些似乎都為我的問題提供了部分解決方案。 這篇文章似乎最接近解決方案,但代碼示例不完整。

很高興接受我的問題的任何建議或解決方案。

這是一個想法......使用線性漸變畫筆

<Window.Resources>
    <LinearGradientBrush x:Key="gb" StartPoint="0 0" EndPoint="1 0">
        <LinearGradientBrush.GradientStops>
            <GradientStop Offset="0.0" Color="Red"/>
            <GradientStop Offset="0.1" Color="Black"/>
            <GradientStop Offset="0.9" Color="Black"/>
            <GradientStop Offset="1.0" Color="Red"/>
        </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
</Window.Resources>
<Grid>
    <Line X1="100" X2="200" Y1="100" Y2="100" Stroke="{StaticResource gb}" StrokeThickness="5"/>
</Grid>

你可以自己動手。 這是我找到並修改以滿足我的需求的代碼。 我添加了CapStrokeCapStrokeThickness屬性

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace LineCaps
{

    public class CappedLine: FrameworkElement
    {        
        protected override void  OnRender(DrawingContext dc)
        {
            Point pos, tangent;
            double angleInRadians;
            double angleInDegrees;
            TransformGroup tg;
            Pen pen = new Pen(Stroke, StrokeThickness);
            dc.DrawGeometry(null, pen, LinePath);

            Pen capPen = new Pen(CapStroke, CapStrokeThickness);
            if (BeginCap != null)
            {
                LinePath.GetPointAtFractionLength(0.01d, out pos, out tangent);
                angleInRadians = Math.Atan2(tangent.Y, tangent.X) + Math.PI;
                angleInDegrees = angleInRadians * 180 / Math.PI + 180;
                tg = new TransformGroup();
                tg.Children.Add(new RotateTransform(angleInDegrees));
                LinePath.GetPointAtFractionLength(0.0d, out pos, out tangent);
                tg.Children.Add(new TranslateTransform(pos.X, pos.Y));
                dc.PushTransform(tg);
                dc.DrawGeometry(CapStroke, capPen, BeginCap);
                dc.Pop();
            }
            if (EndCap != null)
            {
                LinePath.GetPointAtFractionLength(0.99, out pos, out tangent);
                angleInRadians = Math.Atan2(tangent.Y, tangent.X) + Math.PI;
                angleInDegrees = angleInRadians * 180 / Math.PI;
                tg = new TransformGroup();
                tg.Children.Add(new RotateTransform(angleInDegrees));
                LinePath.GetPointAtFractionLength(1, out pos, out tangent);
                tg.Children.Add(new TranslateTransform(pos.X, pos.Y));
                dc.PushTransform(tg);
                dc.DrawGeometry(CapStroke, capPen, EndCap);
            }         
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            //TODO: Consider creating the Pen once when Stroke and StrokeThickness are set
            return LinePath.GetRenderBounds(new Pen(Stroke, StrokeThickness)).Size;
        }

        public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(typeof(CappedLine));
        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }

        public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(typeof(CappedLine));
        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public static DependencyProperty CapStrokeProperty =
        DependencyProperty.Register(
            "CapStroke",
            typeof(Brush),
            typeof(CappedLine));
        public Brush CapStroke
        {
            get { return (Brush)GetValue(CapStrokeProperty); }
            set { SetValue(CapStrokeProperty, value); }
        }

        public static readonly DependencyProperty CapStrokeThicknessProperty =
        DependencyProperty.Register(
            "CapStrokeThickness",
            typeof(double),
            typeof(CappedLine));

        public double CapStrokeThickness
        {
            get { return (double)GetValue(CapStrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public static readonly DependencyProperty LinePathProperty =
            DependencyProperty.Register("LinePath", typeof(PathGeometry), typeof(CappedLine),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                LinePathChangedCallback));
        static void LinePathChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            CappedLine me = sender as CappedLine;
            if (null != me)
            {
                me.OnLinePathChanged((PathGeometry)args.NewValue);
            }
        }
        public PathGeometry LinePath
        {
            get { return (PathGeometry)GetValue(LinePathProperty); }
            set { SetValue(LinePathProperty, value); }
        }
        public virtual void OnLinePathChanged(PathGeometry value)
        {
        }

        public static readonly DependencyProperty BeginCapProperty =
            DependencyProperty.Register("BeginCap", typeof(Geometry), typeof(CappedLine),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                BeginCapChangedCallback));
        static void BeginCapChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            CappedLine me = sender as CappedLine;
            if (null != me)
            {
                me.OnBeginCapChanged((Geometry)args.NewValue);
            }
        }
        public Geometry BeginCap
        {
            get { return (Geometry)GetValue(BeginCapProperty); }
            set { SetValue(BeginCapProperty, value); }
        }
        public virtual void OnBeginCapChanged(Geometry value)
        {
        }

        public static readonly DependencyProperty EndCapProperty =
            DependencyProperty.Register("EndCap", typeof(Geometry), typeof(CappedLine),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                EndCapChangedCallback));
        static void EndCapChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            CappedLine me = sender as CappedLine;
            if (null != me)
            {
                me.OnEndCapChanged((Geometry)args.NewValue);
            }
        }
        public Geometry EndCap
        {
            get { return (Geometry)GetValue(EndCapProperty); }
            set { SetValue(EndCapProperty, value); }
        }
        public virtual void OnEndCapChanged(Geometry value)
        {
        }
    }
}

然后使用它:

<Window x:Class="LineCaps.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:loc="clr-namespace:LineCaps"
        Title="MainWindow">
    <Viewbox>
        <Canvas Height="350" Width="525">
            <loc:CappedLine BeginCap="M0,0 L6,-6 L6,6 z" EndCap="M0,-3 L0,3 L6,3 L6,-3 z" Stroke="Gold" StrokeThickness="1" CapStroke="Green" CapStrokeThickness="1" Canvas.Left="40" Canvas.Top="60">
                <loc:CappedLine.LinePath>
                    <PathGeometry Figures="M0,0 L120,120" />
                </loc:CappedLine.LinePath>
            </loc:CappedLine>

            <loc:CappedLine EndCap="M0,0 L6,-6 L6,6 z" Stroke="Blue" StrokeThickness="1" CapStroke="Red" CapStrokeThickness="1"  Canvas.Left="40" Canvas.Top="200" RenderTransformOrigin="1.5,0.5">
                <loc:CappedLine.BeginCap>
                    <EllipseGeometry Center="0,0" RadiusX="6" RadiusY="6" />
                </loc:CappedLine.BeginCap>
                <loc:CappedLine.LinePath>
                    <PathGeometry Figures="M0,0 C1,1 10.5,75.5 48.5,66.5 86.5,57.5 53.5,3.5000146 105.5,16.500091 157.5,29.500166 164.5,87.500505 164.5,87.500505" />
                </loc:CappedLine.LinePath>
                <loc:CappedLine.RenderTransform>
                    <RotateTransform Angle="0" />
                </loc:CappedLine.RenderTransform>
            </loc:CappedLine>

        </Canvas>
    </Viewbox>
</Window>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM