【WPF】自定义颜色拾取器

1.界面布局

cpp 复制代码
 <GroupBox
     Padding="0"
     BorderThickness="0.1"
     Foreground="White"
     Header="Color Pick">
     <DockPanel>
         <GroupBox
             Margin="5,0,5,2"
             BorderThickness="0.1"
             DockPanel.Dock="Right"
             Foreground="White"
             Header="Color">
             <WrapPanel
                 Width="200"
                 DockPanel.Dock="Right"
                 Orientation="Vertical">
                 <WrapPanel Margin="5,5,0,0">
                     <Label
                         VerticalContentAlignment="Center"
                         Content="R:"
                         Foreground="White" />
                     <Label
                         Name="Label_R"
                         Margin="5,0,0,0"
                         VerticalContentAlignment="Center"
                         Content="0"
                         Foreground="White" />
                 </WrapPanel>
                 <WrapPanel Margin="5,5,0,0">
                     <Label
                         VerticalContentAlignment="Center"
                         Content="G:"
                         Foreground="White" />
                     <Label
                         Name="Label_G"
                         Margin="5,0,0,0"
                         VerticalContentAlignment="Center"
                         Content="0"
                         Foreground="White" />
                 </WrapPanel>
                 <WrapPanel Margin="5,5,0,0">
                     <Label
                         VerticalContentAlignment="Center"
                         Content="B:"
                         Foreground="White" />
                     <Label
                         Name="Label_B"
                         Margin="5,0,0,0"
                         VerticalContentAlignment="Center"
                         Content="0"
                         Foreground="White" />
                 </WrapPanel>
                 <WrapPanel Background="Black">
                     <Image
                         x:Name="Image_Clolor"
                         Width="200"
                         Height="150"
                         Margin="0" />
                 </WrapPanel>
             </WrapPanel>
         </GroupBox>
         <GroupBox
             Name="WrapPanel_Image"
             Padding="0,0,0,0"
             HorizontalContentAlignment="Stretch"
             VerticalContentAlignment="Stretch"
             Background="Black"
             BorderThickness="0"
             ClipToBounds="True"
             Cursor="Cross"
             DockPanel.Dock="Left">
             <Image
                 x: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.后台实现

csharp 复制代码
 /// <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的BitmapImage
             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_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.效果

相关推荐
张人玉7 小时前
WPF 常用样式属性及示例笔记
笔记·wpf
张人玉8 小时前
WPF布局控件(界面骨架核心)
开发语言·c#·wpf·布局控件
亦陈不染12 小时前
c#入门详解(刘铁锰)06 - 数据持久化:TXT文本保存、序列化与反序列化(附详细源码)
开发语言·计算机视觉·c#·wpf
应用市场14 小时前
楼灯光矩阵显示系统:从理论到实践的完整技术方案
线性代数·矩阵·wpf
虚行18 小时前
WPF入门
开发语言·c#·wpf
周杰伦fans19 小时前
MahApps.Metro WPF 开发使用过程中遇到的问题 - 未能加载文件或程序集“Microsoft.Xaml.Behaviors,
microsoft·wpf
△曉風殘月〆1 天前
WPF中的坐标转换
wpf
一个天蝎座 白勺 程序猿1 天前
深度解析:通过ADO.NET驱动Kdbndp高效连接与操作Kingbase数据库
数据库·.net·wpf·kingbase·金仓数据库
时光追逐者1 天前
一个使用 WPF 开发的 Diagram 画板工具(包含流程图FlowChart,思维导图MindEditor)
c#·.net·wpf·流程图