自定义WPF颜色选择器的实现

在开发图形界面应用程序时,经常需要为用户界面元素设置颜色。这看似是一个简单的任务,因为互联网上有许多现成的颜色选择器可以使用。然而,当被告知需要一个外观和感觉类似于Office 2007颜色选择器的控件时,决定自己实现一个。以下是创建的颜色选择器的功能和实现细节。

功能

颜色选择器具有以下功能:

  • 从预定义的颜色列表中选择颜色
  • 从颜色调色板中选择自定义颜色
  • 使用滑块在自定义颜色选择模式下调整选定颜色的透明度
  • 在WPF应用程序中的任何地方易于使用,只需一个绑定属性即可设置选定的颜色

实现

提供的源代码非常自解释且易于理解。以下是一些感兴趣的要点。首先,让看看如何在应用程序中使用它。

基本上,该控件有三个文件,因此将其打包成一个DLL。

<CustomWPFColorPicker:ColorPickerControlView x:Name="ForeColorPicker"/>

控件有一个依赖属性"CurrentColor",当从选择器中选择颜色时,无论是从预定义的颜色列表还是高级颜色调色板,都会更新此属性。

public static DependencyProperty CurrentColorProperty = DependencyProperty.Register("CurrentColor", typeof(SolidColorBrush), typeof(ColorPickerControlView), new PropertyMetadata(Brushes.Black));

选择器是一个ToggleButton,样式略有编辑,以在<border>内显示CurrentColor。一个Popup包含预定义的颜色,就像Office 2007中的那样。这些是一组按钮,每个按钮通过命令参数表示一种颜色。

<Button Click="Button_Click" Style="{StaticResource ColorButtonStyleFirstRow}" Command="{x:Static CustomWPFColorPicker:ColorPickerControlView.SelectColorCommand}" CommandParameter="#FFFFFF" Margin="3,4,3,4" Background="#FFFFFF"/>

"更多颜色"按钮用于打开一个模型对话框,其中包含高级选择器,用户可以从颜色调色板中用鼠标选择颜色。

颜色调色板是一个JPG图像,在mousedown事件期间读取4位ARGB颜色。

private void Image_MouseDown(object sender, MouseButtonEventArgs e) { try { var cb = new CroppedBitmap((BitmapSource)(((Image)e.Source).Source), new Int32Rect((int)Mouse.GetPosition(e.Source as Image).X, (int)Mouse.GetPosition(e.Source as Image).Y, 1, 1)); _pixels = new byte[4]; try { cb.CopyPixels(_pixels, 4, 0); UpdateCurrentColor(); UpdateMarkerPosition(); } catch { } UpdateSlider(); } catch (Exception) { } }

使用这些位,更新颜色:

private void UpdateCurrentColor() { CurrentColor = Color.FromRgb(_pixels[2], _pixels[1], _pixels[0]); currentColorBorder.Background = new SolidColorBrush(Color.FromRgb(_pixels[2], _pixels[1], _pixels[0])); brightnessSlider.Value = 0.5; SelectedCurrentColor = new SolidColorBrush(CurrentColor); }

使用滑块调整颜色值,以便用户可以获得更多颜色的阴影。编辑了默认WPF滑块控件的样式,以获得演示中看到的外观。它的背景反映了用户在更改值时将获得的颜色阴影。为此,使用了LinearGradientBrush,它在0、0.5和1点有3个GradientStop。在零点颜色是白色,在0.5点颜色是选定的颜色,在1点是黑色。

<LinearGradientBrush x:Key="BrightnessGradient" StartPoint="0,1" EndPoint="0,0" ColorInterpolationMode="ScRgbLinearInterpolation"> <GradientStop Offset="0" Color="sc# 1, 0,0,0"/> <GradientStop Offset="0.5" Color="sc# 1, 0.5,0.5,0.5"/> <GradientStop Offset="1" Color="sc# 1, 1,1,1"/> </LinearGradientBrush>

当滑块值更改时,根据滑块的值计算颜色值。这里有两个特殊情况需要考虑。当滑块值接近0时,颜色应该更接近白色。当滑块值接近1时,它应该更接近黑色。在0时颜色变为白色,在1时是黑色。为此,设计了一个高效的算法,非常简单易懂。请注意,这里不仅仅是改变颜色的alpha值,而是计算从白色到黑色的选定颜色和正在调整阴影的颜色的阴影。

void BrightnessSliderValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (_pixels == null) { _pixels = new byte[3]; _pixels[2] = CurrentColor.R; _pixels[1] = CurrentColor.G; _pixels[0] = CurrentColor.B; } var nc = Color.FromRgb(_pixels[2], _pixels[1], _pixels[0]); var f = (float)e.NewValue; float r, g, b; const float a = 1; if (f >= 0.5f) { r = nc.ScR + (1 - nc.ScR) * (f - 0.5f) * 2; g = nc.ScG + (1 - nc.ScG) * (f - 0.5f) * 2; b = nc.ScB + (1 - nc.ScB) * (f - 0.5f) * 2; } else { r = nc.ScR * f * 2; g = nc.ScG * f * 2; b = nc.ScB * f * 2; } CurrentColor = Color.FromScRgb(a, r, g, b); currentColorBorder.Background = new SolidColorBrush(CurrentColor); }

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485