基于WPF實(shí)現(xiàn)顏色選擇器控件
WPF 實(shí)現(xiàn)顏色選擇器控件
- 框架使用
.NET4 至 .NET6
; Visual Studio 2022
;
實(shí)現(xiàn)代碼
1)新增 ColorPicker.cs
代碼如下:
- 包含一個(gè)Slider(用于選擇色調(diào))、一個(gè)Canvas(用于選擇飽和度和亮度)、一個(gè)Thumb(拖動(dòng)選擇飽和度和亮度的指示器)和一個(gè)Button(用于切換顏色類型)。
- 通過使用ColorPicker控件,用戶可以選擇一個(gè)顏色,并且可以通過綁定SelectedColor屬性來獲取所選顏色。這個(gè)屬性是一個(gè)依賴屬性,支持雙向綁定,并且當(dāng)顏色發(fā)生改變時(shí)會(huì)觸發(fā)SelectedColorChanged事件。
- ColorType屬性用于指定顏色類型,可以選擇RGB、HSL或HEX三種類型之一。當(dāng)用戶點(diǎn)擊Button時(shí),可以循環(huán)切換顏色類型。
- 在控件的模板中,通過TemplatePart特性標(biāo)記了四個(gè)重要的子元素:HueSlider、Canvas、Thumb和Button。在OnApplyTemplate方法中,根據(jù)模板找到這些子元素,并注冊相應(yīng)的事件處理程序。
- 控件通過使用顏色轉(zhuǎn)換工具類ColorUtil實(shí)現(xiàn)顏色的轉(zhuǎn)換和計(jì)算。當(dāng)用戶在Canvas上點(diǎn)擊或拖動(dòng)Thumb時(shí),會(huì)計(jì)算得到相應(yīng)的HSB(色調(diào)、飽和度、亮度)值,并將其設(shè)置為依賴屬性HSB的值。然后根據(jù)HSB的值計(jì)算出對應(yīng)的顏色,并更新SelectedColor屬性的值。
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
代碼如下:
- 在Canvas的背景中使用了DrawingBrush和DrawingGroup來創(chuàng)建漸變和幾何形狀。
- 創(chuàng)建了一個(gè)線性漸變刷(LinearGradientBrush),漸變的起點(diǎn)是(0,0),終點(diǎn)是(1,0)。其中的GradientStop標(biāo)簽指定了兩個(gè)漸變停止點(diǎn),一個(gè)偏移量為0,顏色為白色,另一個(gè)偏移量為1,顏色綁定到了HueColor屬性。
- 接下來,同樣方式創(chuàng)建了另一個(gè)線性漸變刷,漸變的起點(diǎn)是(0,0),終點(diǎn)是(0,1)。GradientStop指定了兩個(gè)漸變停止點(diǎn),一個(gè)偏移量為0,顏色為透明("#00000000"),另一個(gè)偏移量為1,顏色為黑色。
<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)新增顏色轉(zhuǎn)換工具類 ColorUtil.cs
代碼如下:
- 包含了將 HSL 顏色空間轉(zhuǎn)換為 RGB 顏色空間以及將 RGB 顏色空間轉(zhuǎn)換為 HSL 顏色空間的方法。
- ConvertHSLToColor 方法用于將 HSL 顏色轉(zhuǎn)換為 RGB 顏色。HSLToRgb 方法實(shí)現(xiàn)了將 HSL 顏色轉(zhuǎn)換為 RGB 顏色的算法,而 SetColor 方法用于在計(jì)算過程中設(shè)置顏色值。
- RgbToHSL 方法用于將 RGB 顏色轉(zhuǎn)換為 HSL 顏色。HsbFromColor 方法則實(shí)現(xiàn)了從 RGB 顏色獲取 HSB(色相、飽和度、亮度)的算法,并修改了傳入的引用類型參數(shù)。ColorFromAhsb 和 ColorFromHsb 方法分別用于根據(jù) AHSB(透明度、色相、飽和度、亮度)和 HSB 值創(chuàng)建顏色對象。
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?/>
效果圖
到此這篇關(guān)于基于WPF實(shí)現(xiàn)顏色選擇器控件的文章就介紹到這了,更多相關(guān)WPF顏色選擇內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用iCSharpcode進(jìn)行文件壓縮實(shí)現(xiàn)方法
這篇文章主要介紹了C#使用iCSharpcode進(jìn)行文件壓縮實(shí)現(xiàn)方法,末尾附有完整實(shí)例,有助于大家參考借鑒,需要的朋友可以參考下2014-08-08WinForm實(shí)現(xiàn)同時(shí)讓兩個(gè)窗體有激活效果的特效實(shí)例
這篇文章主要介紹了WinForm實(shí)現(xiàn)同時(shí)讓兩個(gè)窗體有激活效果的特效實(shí)例,基于windows api實(shí)現(xiàn)一個(gè)窗體激活的時(shí)候給另外一個(gè)發(fā)消息的特效,在進(jìn)行C#項(xiàng)目開發(fā)時(shí)有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-09-09C#如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉
多進(jìn)程開發(fā)經(jīng)常會(huì)遇到主進(jìn)程關(guān)閉,子進(jìn)程需要跟隨主進(jìn)程一同關(guān)閉,比如調(diào)ffmpeg命令行實(shí)現(xiàn)的錄屏程序等,下面我們就來看看C#是如何實(shí)現(xiàn)子進(jìn)程跟隨主進(jìn)程關(guān)閉的吧2024-04-04Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析
這篇文章主要介紹了Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析,對于新手來說有不錯(cuò)的借鑒學(xué)習(xí)價(jià)值,需要的朋友可以參考下2014-07-07