C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > WPF颜色选择

基于WPF实现颜色选择器控件

作者:WPF开发者

这篇文章主要介绍了如何基于WPF实现简单的颜色选择器控件,文中的示例代码讲解详细,对我们学习或工作有一定帮助,需要的小伙伴可以参考一下

WPF 实现颜色选择器控件

实现代码

1)新增 ColorPicker.cs 代码如下:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using WPFDevelopers.Utilities;
namespace WPFDevelopers.Controls
{
    [TemplatePart(Name = HueSliderColorTemplateName, Type = typeof(Slider))]
    [TemplatePart(Name = CanvasTemplateName, Type = typeof(Canvas))]
    [TemplatePart(Name = ThumbTemplateName, Type = typeof(Thumb))]
    [TemplatePart(Name = ButtonTemplateName, Type = typeof(Button))]
    public class ColorPicker : Control
    {
        private const string HueSliderColorTemplateName = "PART_HueSlider";
        private const string CanvasTemplateName = "PART_Canvas";
        private const string ThumbTemplateName = "PART_Thumb";
        private const string ButtonTemplateName = "PART_Button";
        private static readonly DependencyPropertyKey HueColorPropertyKey =
            DependencyProperty.RegisterReadOnly("HueColor", typeof(Color), typeof(ColorPicker),
                new PropertyMetadata(Colors.Red));
        public static readonly DependencyProperty HueColorProperty = HueColorPropertyKey.DependencyProperty;
        public static readonly DependencyProperty SelectedColorProperty =
            DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPicker),
                new FrameworkPropertyMetadata(Colors.Red, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    OnSelectedColorChanged));
        private static readonly DependencyPropertyKey HSBPropertyKey =
            DependencyProperty.RegisterReadOnly("HSB", typeof(HSB), typeof(ColorPicker),
                new PropertyMetadata(new HSB()));
        public static readonly DependencyProperty HSBHProperty = HSBPropertyKey.DependencyProperty;
        public static readonly DependencyProperty ColorTypeProperty =
            DependencyProperty.Register("ColorType", typeof(ColorTypeEnum), typeof(ColorPicker),
                new PropertyMetadata(ColorTypeEnum.RGB));
        private Button _button;
        private Canvas _canvas;
        private Slider _hueSliderColor;
        private bool _isInnerUpdateSelectedColor;
        private Thumb _thumb;
        private ColorTypeEnum[] colorTypeEnums;
        private int currentGridStateIndex;
        static ColorPicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker),
                new FrameworkPropertyMetadata(typeof(ColorPicker)));
        }
        public Color HueColor => (Color) GetValue(HueColorProperty);
        public Color SelectedColor
        {
            get => (Color) GetValue(SelectedColorProperty);
            set => SetValue(SelectedColorProperty, value);
        }
        public HSB HSB => (HSB) GetValue(HSBHProperty);
        public ColorTypeEnum ColorType
        {
            get => (ColorTypeEnum) GetValue(ColorTypeProperty);
            set => SetValue(ColorTypeProperty, value);
        }
        private static void OnSelectedColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ctrl = d as ColorPicker;
            if (ctrl._isInnerUpdateSelectedColor)
            {
                ctrl._isInnerUpdateSelectedColor = false;
                return;
            }
            var color = (Color) e.NewValue;
            double h = 0, s = 0, b = 0;
            ColorUtil.HsbFromColor(color, ref h, ref s, ref b);
            var hsb = new HSB {H = h, S = s, B = b};
            ctrl.SetValue(HueColorPropertyKey, ColorUtil.ColorFromHsb(hsb.H, 1, 1));
            ctrl.SetValue(HSBPropertyKey, hsb);
            Canvas.SetLeft(ctrl._thumb, s * ctrl._canvas.ActualWidth - ctrl._thumb.ActualWidth / 2);
            Canvas.SetTop(ctrl._thumb, (1 - b) * ctrl._canvas.ActualHeight - ctrl._thumb.ActualHeight / 2);
            ctrl._hueSliderColor.Value = 1 - h;
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            if (_hueSliderColor != null)
                _hueSliderColor.ValueChanged -= HueSliderColor_OnValueChanged;
            _canvas = GetTemplateChild(CanvasTemplateName) as Canvas;
            if (_canvas != null)
            {
                _canvas.Loaded += Canvas_Loaded;
                _canvas.MouseUp += Canvas_MouseUp;
            }
            _thumb = GetTemplateChild(ThumbTemplateName) as Thumb;
            if (_thumb != null)
                _thumb.DragDelta += Thumb_DragDelta;
            _hueSliderColor = GetTemplateChild(HueSliderColorTemplateName) as Slider;
            if (_hueSliderColor != null)
                _hueSliderColor.ValueChanged += HueSliderColor_OnValueChanged;
            _button = GetTemplateChild(ButtonTemplateName) as Button;
            currentGridStateIndex = 0;
            colorTypeEnums = (ColorTypeEnum[]) Enum.GetValues(typeof(ColorTypeEnum));
            if (_button != null)
                _button.Click += Button_Click;
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            currentGridStateIndex = (currentGridStateIndex + 1) % colorTypeEnums.Length;
            ColorType = colorTypeEnums[currentGridStateIndex];
        }
        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            var canvasPosition = e.GetPosition(_canvas);
            GetHSB(canvasPosition);
        }
        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            var canvasPosition = e.GetPosition(_canvas);
            GetHSB(canvasPosition);
        }
        private void GetHSB(Point point, bool isMove = true)
        {
            var newLeft = point.X - _thumb.ActualWidth / 2;
            var newTop = point.Y - _thumb.ActualHeight / 2;
            var thumbW = _thumb.ActualWidth / 2;
            var thumbH = _thumb.ActualHeight / 2;
            var canvasRight = _canvas.ActualWidth - thumbW;
            var canvasBottom = _canvas.ActualHeight - thumbH;
            if (newLeft < -thumbW)
                newLeft = -thumbW;
            else if (newLeft > canvasRight)
                newLeft = canvasRight;
            if (newTop < -thumbH)
                newTop = -thumbH;
            else if (newTop > canvasBottom)
                newTop = canvasBottom;
            if (isMove)
            {
                Canvas.SetLeft(_thumb, newLeft);
                Canvas.SetTop(_thumb, newTop);
            }
            var hsb = new HSB
            {
                H = HSB.H, S = (newLeft + thumbW) / _canvas.ActualWidth,
                B = 1 - (newTop + thumbH) / _canvas.ActualHeight
            };
            SetValue(HSBPropertyKey, hsb);
            var currentColor = ColorUtil.ColorFromAhsb(1, HSB.H, HSB.S, HSB.B);
            if (SelectedColor != currentColor)
            {
                _isInnerUpdateSelectedColor = true;
                SelectedColor = currentColor;
            }
        }
        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            var point = Mouse.GetPosition(_canvas);
            GetHSB(point);
        }
        private void Canvas_Loaded(object sender, RoutedEventArgs e)
        {
            var width = (int) _canvas.ActualWidth;
            var height = (int) _canvas.ActualHeight;
            var point = new Point(width - _thumb.ActualWidth / 2, -_thumb.ActualHeight / 2);
            Canvas.SetLeft(_thumb, point.X);
            Canvas.SetTop(_thumb, point.Y);
            var hsb = new HSB {H = _hueSliderColor.Value, S = HSB.S, B = HSB.B};
            SetValue(HSBPropertyKey, hsb);
        }
        private void HueSliderColor_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (DoubleUtil.AreClose(HSB.H, e.NewValue))
                return;
            var hsb = new HSB {H = 1 - e.NewValue, S = HSB.S, B = HSB.B};
            SetValue(HSBPropertyKey, hsb);
            SetValue(HueColorPropertyKey, ColorUtil.ColorFromHsb(HSB.H, 1, 1));
            var newLeft = Canvas.GetLeft(_thumb);
            var newTop = Canvas.GetTop(_thumb);
            var point = new Point(newLeft, newTop);
            GetHSB(point, false);
        }
    }
    public enum ColorTypeEnum
    {
        RGB,
        HSL,
        HEX
    }
}

2)新增 ColorPicker.xaml 代码如下:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:WPFDevelopers.Controls"
    xmlns:convert="clr-namespace:WPFDevelopers.Converts"
    xmlns:helpers="clr-namespace:WPFDevelopers.Helpers"
    xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
    xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Basic/ControlBasic.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <convert:ColorToBrushConverter x:Key="WD.ColorToBrushConverter" />
    <convert:ColorToRedConverter x:Key="WD.ColorToRedConverter" />
    <convert:ColorToGreenConverter x:Key="WD.ColorToGreenConverter" />
    <convert:ColorToBlueConverter x:Key="WD.ColorToBlueConverter" />
    <convert:ColorTypeToVisibilityConverter x:Key="WD.ColorTypeToVisibilityConverter" />
    <convert:ColorToStringConverter x:Key="WD.ColorToStringConverter" />
    <convert:HToColorConverter x:Key="WD.HToColorConverter" />
    <convert:SToColorConverter x:Key="WD.SToColorConverter" />
    <convert:LToColorConverter x:Key="WD.LToColorConverter" />
    <LinearGradientBrush x:Key="WD.ColorPickerRainbowBrush" po:Freeze="True">
        <GradientStop Color="#FF0000" />
        <GradientStop Offset="0.167" Color="#FF00FF" />
        <GradientStop Offset="0.334" Color="#0000FF" />
        <GradientStop Offset="0.501" Color="#00FFFF" />
        <GradientStop Offset="0.668" Color="#00FF00" />
        <GradientStop Offset="0.835" Color="#FFFF00" />
        <GradientStop Offset="1" Color="#FF0000" />
    </LinearGradientBrush>
    <ControlTemplate x:Key="WD.ColorPickerSliderThumbTemplate" TargetType="Thumb">
        <Border
            Width="{TemplateBinding Width}"
            Height="{TemplateBinding Height}"
            Background="Transparent"
            BorderBrush="White"
            BorderThickness="3"
            CornerRadius="{Binding ActualWidth, RelativeSource={RelativeSource Self}, Converter={StaticResource WD.HalfValueConverter}}" />
    </ControlTemplate>
    <Style x:Key="WD.ColorPickerSliderRepeatButtonBaseStyle" TargetType="RepeatButton">
        <Setter Property="OverridesDefaultStyle" Value="true" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Focusable" Value="false" />
        <Setter Property="IsTabStop" Value="false" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="RepeatButton">
                    <Rectangle
                        Width="{TemplateBinding Width}"
                        Height="{TemplateBinding Height}"
                        Fill="{TemplateBinding Background}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="WD.ColorPickerSlider" TargetType="{x:Type Slider}">
        <Setter Property="Background" Value="{StaticResource WD.ColorPickerRainbowBrush}" />
        <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
        <Setter Property="Orientation" Value="Horizontal" />
        <Setter Property="Height" Value="15" />
        <Setter Property="Margin" Value="4,0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Slider}">
                    <controls:SmallPanel>
                        <Border
                            MaxWidth="{TemplateBinding MaxWidth}"
                            Margin="{TemplateBinding Margin}"
                            Background="{TemplateBinding Background}"
                            CornerRadius="2" />
                        <Track x:Name="PART_Track" Orientation="{TemplateBinding Orientation}">
                            <Track.DecreaseRepeatButton>
                                <RepeatButton Command="{x:Static Slider.DecreaseLarge}" Style="{StaticResource WD.ColorPickerSliderRepeatButtonBaseStyle}" />
                            </Track.DecreaseRepeatButton>
                            <Track.IncreaseRepeatButton>
                                <RepeatButton Command="{x:Static Slider.IncreaseLarge}" Style="{StaticResource WD.ColorPickerSliderRepeatButtonBaseStyle}" />
                            </Track.IncreaseRepeatButton>
                            <Track.Thumb>
                                <Thumb
                                    x:Name="Thumb"
                                    Width="15"
                                    Height="15"
                                    Focusable="False"
                                    OverridesDefaultStyle="True"
                                    Template="{StaticResource WD.ColorPickerSliderThumbTemplate}">
                                    <Thumb.Effect>
                                        <DropShadowEffect Opacity=".6" ShadowDepth="0" />
                                    </Thumb.Effect>
                                </Thumb>
                            </Track.Thumb>
                        </Track>
                    </controls:SmallPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style
        x:Key="WD.ColorPicker"
        BasedOn="{StaticResource WD.ControlBasicStyle}"
        TargetType="{x:Type controls:ColorPicker}">
        <Setter Property="Width" Value="260" />
        <Setter Property="Height" Value="200" />
        <Setter Property="Margin" Value="2" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="BorderBrush" Value="{DynamicResource WD.BaseSolidColorBrush}" />
        <Setter Property="Background" Value="{DynamicResource WD.BackgroundSolidColorBrush}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:ColorPicker}">
                    <Border
                        Margin="{TemplateBinding Margin}"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Canvas
                                x:Name="PART_Canvas"
                                Margin="1,1,1,0"
                                ClipToBounds="True">
                                <Canvas.Background>
                                    <DrawingBrush>
                                        <DrawingBrush.Drawing>
                                            <DrawingGroup>
                                                <GeometryDrawing>
                                                    <GeometryDrawing.Brush>
                                                        <LinearGradientBrush EndPoint="1,0">
                                                            <GradientStop Offset="0" Color="White" />
                                                            <GradientStop Offset="1" Color="{Binding HueColor, RelativeSource={RelativeSource TemplatedParent}}" />
                                                        </LinearGradientBrush>
                                                    </GeometryDrawing.Brush>
                                                    <GeometryDrawing.Geometry>
                                                        <RectangleGeometry Rect="0,0,5,5" />
                                                    </GeometryDrawing.Geometry>
                                                </GeometryDrawing>
                                                <GeometryDrawing>
                                                    <GeometryDrawing.Brush>
                                                        <LinearGradientBrush EndPoint="0,1">
                                                            <GradientStop Offset="0" Color="#00000000" />
                                                            <GradientStop Offset="1" Color="{StaticResource WD.BlackColor}" />
                                                        </LinearGradientBrush>
                                                    </GeometryDrawing.Brush>
                                                    <GeometryDrawing.Geometry>
                                                        <RectangleGeometry Rect="0,0,5,5" />
                                                    </GeometryDrawing.Geometry>
                                                </GeometryDrawing>
                                            </DrawingGroup>
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Canvas.Background>
                                <Thumb
                                    x:Name="PART_Thumb"
                                    Width="15"
                                    Height="15"
                                    Background="Transparent"
                                    BorderBrush="White"
                                    BorderThickness="3">
                                    <Thumb.Template>
                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                            <controls:SmallPanel>
                                                <Border
                                                    Background="{TemplateBinding Background}"
                                                    BorderBrush="{TemplateBinding BorderBrush}"
                                                    BorderThickness="{TemplateBinding BorderThickness}"
                                                    CornerRadius="{Binding ActualWidth, RelativeSource={RelativeSource Self}, Converter={StaticResource WD.HalfValueConverter}}"
                                                    SnapsToDevicePixels="True">
                                                    <Border.Effect>
                                                        <DropShadowEffect Opacity=".6" ShadowDepth="0" />
                                                    </Border.Effect>
                                                </Border>
                                            </controls:SmallPanel>
                                        </ControlTemplate>
                                    </Thumb.Template>
                                </Thumb>
                            </Canvas>
                            <Grid Grid.Row="1" Margin="6,5,6,0">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Ellipse
                                    Width="25"
                                    Height="25"
                                    Margin="0,0,4,0"
                                    Fill="{TemplateBinding SelectedColor,
                                                           Converter={StaticResource WD.ColorToBrushConverter}}">
                                    <Ellipse.Effect>
                                        <DropShadowEffect Opacity=".6" ShadowDepth="0" />
                                    </Ellipse.Effect>
                                </Ellipse>
                                <Slider
                                    Name="PART_HueSlider"
                                    Grid.Column="1"
                                    Width="Auto"
                                    IsMoveToPointEnabled="True"
                                    LargeChange="0.01"
                                    Maximum="1"
                                    SmallChange="0.01"
                                    Style="{StaticResource WD.ColorPickerSlider}"
                                    Value="1" />
                            </Grid>
                            <Grid
                                Grid.Row="2"
                                Margin="4"
                                VerticalAlignment="Center">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Grid.Resources>
                                    <Style TargetType="{x:Type StackPanel}">
                                        <Setter Property="Margin" Value="4,0" />
                                    </Style>
                                    <Style
                                        x:Key="WD.TextBoxColorPicker"
                                        BasedOn="{StaticResource WD.DefaultTextBox}"
                                        TargetType="{x:Type TextBox}">
                                        <Setter Property="VerticalContentAlignment" Value="Center" />
                                        <Setter Property="TextAlignment" Value="Center" />
                                        <Setter Property="Width" Value="50" />
                                    </Style>
                                    <Style BasedOn="{StaticResource WD.NumericBox}" TargetType="{x:Type controls:NumericBox}">
                                        <Setter Property="VerticalContentAlignment" Value="Center" />
                                        <Setter Property="TextAlignment" Value="Center" />
                                        <Setter Property="Width" Value="50" />
                                        <Setter Property="UpDownButtonsWidth" Value="0" />
                                        <Setter Property="Maximum" Value="255" />
                                        <Setter Property="Minimum" Value="0" />
                                    </Style>
                                    <Style TargetType="{x:Type TextBlock}">
                                        <Setter Property="HorizontalAlignment" Value="Center" />
                                        <Setter Property="Foreground" Value="{DynamicResource WD.PrimaryTextSolidColorBrush}" />
                                        <Setter Property="FontSize" Value="10" />
                                    </Style>
                                </Grid.Resources>
                                <Button
                                    Name="PART_Button"
                                    Grid.Column="0"
                                    Width="30"
                                    Height="30"
                                    Margin="0,0,4,0"
                                    helpers:ElementHelper.IsRound="True"
                                    Style="{StaticResource WD.NormalButton}">
                                    <controls:PathIcon Kind="UnfoldMore" />
                                </Button>
                                <UniformGrid
                                    Grid.Column="1"
                                    Rows="1"
                                    Visibility="{Binding ColorType, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorTypeToVisibilityConverter}, ConverterParameter={x:Static controls:ColorTypeEnum.RGB}}">
                                    <StackPanel>
                                        <controls:NumericBox Value="{Binding SelectedColor, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorToRedConverter}}" />
                                        <TextBlock Text="R" />
                                    </StackPanel>
                                    <StackPanel>
                                        <controls:NumericBox Value="{Binding SelectedColor, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorToGreenConverter}}" />
                                        <TextBlock Text="G" />
                                    </StackPanel>
                                    <StackPanel>
                                        <controls:NumericBox Value="{Binding SelectedColor, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorToBlueConverter}}" />
                                        <TextBlock Text="B" />
                                    </StackPanel>
                                </UniformGrid>
                                <UniformGrid
                                    Grid.Column="1"
                                    Rows="1"
                                    Visibility="{Binding ColorType, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorTypeToVisibilityConverter}, ConverterParameter={x:Static controls:ColorTypeEnum.HSL}}">
                                    <StackPanel>
                                        <TextBox
                                            helpers:TextBoxHelper.AllowOnlyNumericInput="True"
                                            helpers:TextBoxHelper.IsEnterUpdateEnabled="True"
                                            helpers:TextBoxHelper.SelectAllOnClick="True"
                                            Style="{StaticResource WD.TextBoxColorPicker}"
                                            Text="{Binding SelectedColor, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.HToColorConverter}}" />
                                        <TextBlock Text="H" />
                                    </StackPanel>
                                    <StackPanel Grid.Column="1">
                                        <TextBox
                                            helpers:TextBoxHelper.IsEnterUpdateEnabled="True"
                                            helpers:TextBoxHelper.SelectAllOnClick="True"
                                            Style="{StaticResource WD.TextBoxColorPicker}"
                                            Text="{Binding SelectedColor, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.SToColorConverter}}" />
                                        <TextBlock Text="S" />
                                    </StackPanel>
                                    <StackPanel Grid.Column="2">
                                        <TextBox
                                            helpers:TextBoxHelper.IsEnterUpdateEnabled="True"
                                            helpers:TextBoxHelper.SelectAllOnClick="True"
                                            Style="{StaticResource WD.TextBoxColorPicker}"
                                            Text="{Binding SelectedColor, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.LToColorConverter}}" />
                                        <TextBlock Text="L" />
                                    </StackPanel>
                                </UniformGrid>
                                <StackPanel
                                    Grid.Column="1"
                                    Margin="12,0"
                                    Visibility="{Binding ColorType, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorTypeToVisibilityConverter}, ConverterParameter={x:Static controls:ColorTypeEnum.HEX}}">
                                    <TextBox
                                        helpers:TextBoxHelper.IsEnterUpdateEnabled="True"
                                        helpers:TextBoxHelper.SelectAllOnClick="True"
                                        MaxLength="9"
                                        Text="{Binding SelectedColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource WD.ColorToStringConverter}}"
                                        TextAlignment="Center" />
                                    <TextBlock Text="HEX" />
                                </StackPanel>
                            </Grid>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style BasedOn="{StaticResource WD.ColorPicker}" TargetType="{x:Type controls:ColorPicker}" />
</ResourceDictionary>

3)新增颜色转换工具类 ColorUtil.cs 代码如下:

using System;
using System.Windows.Media;
using WPFDevelopers.Controls;
namespace WPFDevelopers.Utilities
{
    public static class ColorUtil
    {
        public static Color ConvertHSLToColor(Color color, double h = double.NaN, double sl = double.NaN,
            double l = double.NaN)
        {
            var hsl = RgbToHSL(color);
            if (!double.IsNaN(h))
                hsl.H = h;
            if (!double.IsNaN(sl))
                hsl.S = sl;
            if (!double.IsNaN(l))
                hsl.L = l;
            var rgb = HSLToRgb(hsl);
            return rgb;
        }
        private static Color HSLToRgb(HSL hslColor)
        {
            var rgbColor = new Color();
            if (hslColor.S == 0)
            {
                rgbColor.R = (byte) (hslColor.L * 255);
                rgbColor.G = (byte) (hslColor.L * 255);
                rgbColor.B = (byte) (hslColor.L * 255);
                rgbColor.A = (byte) (hslColor.A * 255);
                return rgbColor;
            }
            double t1;
            if (hslColor.L < 0.5)
                t1 = hslColor.L * (1.0 + hslColor.S);
            else
                t1 = hslColor.L + hslColor.S - hslColor.L * hslColor.S;
            var t2 = 2.0 * hslColor.L - t1;
            var h = hslColor.H / 360;
            var tR = h + 1.0 / 3.0;
            var r = SetColor(t1, t2, tR);
            var tG = h;
            var g = SetColor(t1, t2, tG);
            var tB = h - 1.0 / 3.0;
            var b = SetColor(t1, t2, tB);
            rgbColor.R = (byte) (r * 255);
            rgbColor.G = (byte) (g * 255);
            rgbColor.B = (byte) (b * 255);
            rgbColor.A = (byte) (hslColor.A * 255);
            return rgbColor;
        }
        private static double SetColor(double t1, double t2, double t3)
        {
            if (t3 < 0) t3 += 1.0;
            if (t3 > 1) t3 -= 1.0;
            double color;
            if (6.0 * t3 < 1)
                color = t2 + (t1 - t2) * 6.0 * t3;
            else if (2.0 * t3 < 1)
                color = t1;
            else if (3.0 * t3 < 2)
                color = t2 + (t1 - t2) * (2.0 / 3.0 - t3) * 6.0;
            else
                color = t2;
            return color;
        }
        public static HSL RgbToHSL(Color rgbColor)
        {
            var hslColor = new HSL();
            var r = (double) rgbColor.R / 255;
            var g = (double) rgbColor.G / 255;
            var b = (double) rgbColor.B / 255;
            var a = (double) rgbColor.A / 255;
            var min = Math.Min(r, Math.Min(g, b));
            var max = Math.Max(r, Math.Max(g, b));
            var delta = max - min;
            if (max == min)
            {
                hslColor.H = 0;
                hslColor.S = 0;
                hslColor.L = max;
                return hslColor;
            }
            hslColor.L = (min + max) / 2;
            if (hslColor.L < 0.5)
                hslColor.S = delta / (max + min);
            else
                hslColor.S = delta / (2.0 - max - min);
            if (r == max) hslColor.H = (g - b) / delta;
            if (g == max) hslColor.H = 2.0 + (b - r) / delta;
            if (b == max) hslColor.H = 4.0 + (r - g) / delta;
            hslColor.H *= 60;
            if (hslColor.H < 0) hslColor.H += 360;
            hslColor.A = a;
            return hslColor;
        }
        public static void HsbFromColor(Color C, ref double H, ref double S, ref double B)
        {
            var r = C.R / 255d;
            var g = C.G / 255d;
            var b = C.B / 255d;
            var max = Math.Max(Math.Max(r, g), b);
            var min = Math.Min(Math.Min(r, g), b);
            var delta = max - min;
            var hue = 0d;
            var saturation = DoubleUtil.GreaterThan(max, 0) ? delta / max : 0.0;
            var brightness = max;
            if (!DoubleUtil.IsZero(delta))
            {
                if (DoubleUtil.AreClose(r, max))
                    hue = (g - b) / delta;
                else if (DoubleUtil.AreClose(g, max))
                    hue = 2 + (b - r) / delta;
                else if (DoubleUtil.AreClose(b, max))
                    hue = 4 + (r - g) / delta;
                hue = hue * 60;
                if (DoubleUtil.LessThan(hue, 0d))
                    hue += 360;
            }
            H = hue / 360d;
            S = saturation;
            B = brightness;
        }
        public static Color ColorFromAhsb(double a, double h, double s, double b)
        {
            var r = ColorFromHsb(h, s, b);
            r.A = (byte) Math.Round(a * 255d);
            return r;
        }
        public static Color ColorFromHsb(double H, double S, double B)
        {
            double red = 0.0, green = 0.0, blue = 0.0;
            if (DoubleUtil.IsZero(S))
            {
                red = green = blue = B;
            }
            else
            {
                var h = DoubleUtil.IsOne(H) ? 0d : H * 6.0;
                var i = (int) Math.Floor(h);
                var f = h - i;
                var r = B * (1.0 - S);
                var s = B * (1.0 - S * f);
                var t = B * (1.0 - S * (1.0 - f));
                switch (i)
                {
                    case 0:
                        red = B;
                        green = t;
                        blue = r;
                        break;
                    case 1:
                        red = s;
                        green = B;
                        blue = r;
                        break;
                    case 2:
                        red = r;
                        green = B;
                        blue = t;
                        break;
                    case 3:
                        red = r;
                        green = s;
                        blue = B;
                        break;
                    case 4:
                        red = t;
                        green = r;
                        blue = B;
                        break;
                    case 5:
                        red = B;
                        green = r;
                        blue = s;
                        break;
                }
            }
            return Color.FromRgb((byte) Math.Round(red * 255.0), (byte) Math.Round(green * 255.0),
                (byte) Math.Round(blue * 255.0));
        }
    }
}

4)示例 代码如下:

xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
<wd:ColorPicker />

效果图

到此这篇关于基于WPF实现颜色选择器控件的文章就介绍到这了,更多相关WPF颜色选择内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文