【WPF】自定义颜色拾取器
1.界面布局
<GroupBoxPadding="0"BorderThickness="0.1"Foreground="White"Header="Color Pick"><DockPanel><GroupBoxMargin="5,0,5,2"BorderThickness="0.1"DockPanel.Dock="Right"Foreground="White"Header="Color"><WrapPanelWidth="200"DockPanel.Dock="Right"Orientation="Vertical"><WrapPanel Margin="5,5,0,0"><LabelVerticalContentAlignment="Center"Content="R:"Foreground="White" /><LabelName="Label_R"Margin="5,0,0,0"VerticalContentAlignment="Center"Content="0"Foreground="White" /></WrapPanel><WrapPanel Margin="5,5,0,0"><LabelVerticalContentAlignment="Center"Content="G:"Foreground="White" /><LabelName="Label_G"Margin="5,0,0,0"VerticalContentAlignment="Center"Content="0"Foreground="White" /></WrapPanel><WrapPanel Margin="5,5,0,0"><LabelVerticalContentAlignment="Center"Content="B:"Foreground="White" /><LabelName="Label_B"Margin="5,0,0,0"VerticalContentAlignment="Center"Content="0"Foreground="White" /></WrapPanel><WrapPanel Background="Black"><Imagex:Name="Image_Clolor"Width="200"Height="150"Margin="0" /></WrapPanel></WrapPanel></GroupBox><GroupBoxName="WrapPanel_Image"Padding="0,0,0,0"HorizontalContentAlignment="Stretch"VerticalContentAlignment="Stretch"Background="Black"BorderThickness="0"ClipToBounds="True"Cursor="Cross"DockPanel.Dock="Left"><Imagex:Name="Image_Img"Width="{Binding ElementName=WrapPanel_Image, Path=ActualWidth}"Height="{Binding ElementName=WrapPanel_Image, Path=ActualHeight}"Margin="-5,0,0,0"HorizontalAlignment="Left"VerticalAlignment="Top"ClipToBounds="True"MouseWheel="Image_Img_MouseWheel"PreviewMouseLeftButtonDown="Image_Img_PreviewMouseLeftButtonDown"PreviewMouseLeftButtonUp="Image_Img_PreviewMouseLeftButtonUp"PreviewMouseMove="Image_Img_PreviewMouseMove"PreviewMouseRightButtonDown="Image_Img_PreviewMouseRightButtonDown"RenderOptions.BitmapScalingMode="Fant"Stretch="Uniform"><Image.RenderTransform><TransformGroup><ScaleTransform x:Name="Image_Img_ScaleTransform" CenterX="0" CenterY="0" ScaleX="1" ScaleY="1" /><TranslateTransform x:Name="Image_Img_TranslateTransform" X="0" Y="0" /></TransformGroup></Image.RenderTransform></Image></GroupBox></DockPanel></GroupBox>
2.后台实现
/// <summary>/// ColorPickerUserControl.xaml 的交互逻辑/// </summary>public partial class ColorPickerUserControl : UserControl{//图像原图private Bitmap originalBitmap;//缩放比率private double ScaleRatio = 0.2;//鼠标按下坐标private System.Windows.Point currentClickPoint = new System.Windows.Point(0, 0);//鼠标按下标识bool isImageLeftButtonDown = false;/// <summary>/// 当前选中颜色/// </summary>public System.Drawing.Color CurrentColor;public ColorPickerUserControl(){InitializeComponent();}/// <summary>/// 资源释放/// </summary>public void Dispose(){try{Image_Img.Source?.Freeze();Image_Img.Source = null;originalBitmap?.Dispose();originalBitmap = null;Image_Clolor.Source?.Freeze();Image_Clolor.Source = null;}catch (Exception ex){throw new Exception(ex.Message);}}/// <summary>/// 加载图像/// </summary>/// <param name="fileName">图像文件路径</param>public void InitImage(string fileName){try{Image_Img.Stretch = Stretch.Uniform;if (File.Exists(fileName)){Task<BitmapImage> task = Task.Run(() =>{//后台读取图像,防止图像太大卡住主线程using (var stream = File.OpenRead(fileName)){var bmp = new BitmapImage();bmp.BeginInit();bmp.StreamSource = stream;bmp.CacheOption = BitmapCacheOption.OnLoad;bmp.EndInit();bmp.Freeze(); // 冻结对象以便跨线程访问originalBitmap = new Bitmap(stream);return bmp;}});task.Wait();Image_Img.Source = task.Result;}}catch (Exception ex){throw new Exception(ex.Message);}}/// <summary>/// 加载图像/// </summary>/// <param name="bitmap">图像</param>public void InitImage(Bitmap bitmap){try{originalBitmap?.Dispose();originalBitmap = null;originalBitmap = new Bitmap(bitmap);// 将Bitmap转换为WPF的BitmapImageBitmapImage bitmapImage;using (MemoryStream memory = new MemoryStream()){bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);memory.Position = 0;bitmapImage = new BitmapImage();bitmapImage.BeginInit();bitmapImage.StreamSource = memory;bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.EndInit();}Image_Img.Source = bitmapImage;bitmapImage?.Freeze();bitmapImage = null;}catch (Exception ex){throw new Exception(ex.Message);}}/// <summary>/// 鼠标左键按下/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Image_Img_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e){try{if (e.ChangedButton != MouseButton.Left) return;var pos = e.GetPosition((System.Windows.Controls.Image)e.Source);currentClickPoint = pos;isImageLeftButtonDown = true;var img = ((System.Windows.Controls.Image)e.Source).Source as BitmapSource;ColorPicker(img, pos);}catch (Exception ex){throw new Exception(ex.Message);}}/// <summary>/// 图像点转真实点/// </summary>/// <param name="thumbnailX"></param>/// <returns></returns>private double ToCamRealX(double thumbnailX){return (thumbnailX / Image_Img.ActualWidth) * (double)(originalBitmap?.Width ?? 0);}/// <summary>/// 图像点转真实点/// </summary>/// <param name="thumbnailY"></param>/// <returns></returns>private double ToCamRealY(double thumbnailY){return (thumbnailY / Image_Img.ActualHeight) * (double)(originalBitmap?.Height ?? 0);}/// <summary>/// 颜色拾取/// </summary>/// <param name="img"></param>/// <param name="pos"></param>/// <exception cref="Exception"></exception>protected void ColorPicker(BitmapSource img, System.Windows.Point pos){try{int stride = img.PixelWidth * 4;int size = img.PixelHeight * stride;byte[] pixels = new byte[(int)size];img.CopyPixels(pixels, stride, 0);// Get pixel//屏幕坐标转图像坐标var x = (int)ToCamRealX(pos.X);var y = (int)ToCamRealY(pos.Y);int index = y * stride + 4 * x;byte red = pixels[index];byte green = pixels[index + 1];byte blue = pixels[index + 2];byte alpha = pixels[index + 3];System.Drawing.Color color = System.Drawing.Color.FromArgb(alpha, blue, green, red);Label_R.Content = color.R.ToString();Label_G.Content = color.G.ToString();Label_B.Content = color.B.ToString();//string ColorText = "#" + color.A.ToString("X2") + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");ColorShow(color);}catch (Exception ex){throw new Exception(ex.Message);}}/// <summary>/// 颜色显示/// </summary>/// <param name="color"></param>/// <exception cref="Exception"></exception>private void ColorShow(System.Drawing.Color color){try{CurrentColor = color;int w = (int)Image_Clolor.Width;int h = (int)Image_Clolor.Height;Bitmap bitmap = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);for (int x = 0; x < w; x++){for (int y = 0; y < h; y++){bitmap.SetPixel(x, y, color);}}BitmapImage bitmapImage;using (MemoryStream memory = new MemoryStream()){bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);memory.Position = 0;bitmapImage = new BitmapImage();bitmapImage.BeginInit();bitmapImage.StreamSource = memory;bitmapImage.CacheOption = BitmapCacheOption.OnLoad;bitmapImage.EndInit();}Image_Clolor.Source = bitmapImage;bitmapImage?.Freeze();bitmapImage = null;bitmap.Dispose();}catch (Exception ex){throw new Exception(ex.Message);}}/// <summary>/// 鼠标滚动缩放/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Image_Img_MouseWheel(object sender, MouseWheelEventArgs e){try{System.Windows.Point center = e.GetPosition(Image_Img);double scale = 0;if (e.Delta > 0){scale = Image_Img_ScaleTransform.ScaleX + ScaleRatio;if (scale > 30){return;}}else{scale = Image_Img_ScaleTransform.ScaleX - ScaleRatio;if (scale < 0.5){return;}}//图像Image_Img_ScaleTransform.ScaleX = scale;Image_Img_ScaleTransform.ScaleY = scale;}catch{}}/// <summary>/// 鼠标移动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Image_Img_PreviewMouseMove(object sender, MouseEventArgs e){try{if (isImageLeftButtonDown == true){if (e.LeftButton == MouseButtonState.Pressed){//移动System.Windows.Point newPoint = e.GetPosition(Image_Img);double deltaX = newPoint.X - currentClickPoint.X;double deltaY = newPoint.Y - currentClickPoint.Y;//图像Image_Img_TranslateTransform.X += deltaX;Image_Img_TranslateTransform.Y += deltaY;}}}catch{}}/// <summary>/// 鼠标放开/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Image_Img_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e){isImageLeftButtonDown = false;}/// <summary>/// 鼠标右键/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Image_Img_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e){Recombination();}/// <summary>/// 重置图像大小/// </summary>private void Recombination(){try{//图像Image_Img_ScaleTransform.ScaleX = 1;Image_Img_ScaleTransform.ScaleY = 1;Image_Img_TranslateTransform.X = 0;Image_Img_TranslateTransform.Y = 0;}catch{}}}
3.效果