欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于WPF開發(fā)簡(jiǎn)單的顏色選擇器

 更新時(shí)間:2023年07月25日 16:51:45   作者:WPF開發(fā)者  
這篇文章主要介紹了如何基于WPF實(shí)現(xiàn)簡(jiǎn)單的顏色選擇器,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的小伙伴可以參考一下

 WPF 簡(jiǎn)單實(shí)現(xiàn)顏色選擇器

  • 框架使用.NET4;
  • Visual Studio 2022;

實(shí)現(xiàn)代碼

1)新增 xaml 代碼如下:

  • 定義一個(gè)WriteableBitmap用于記錄顏色緩沖值。
  • XAML中定義Canvas設(shè)置背景為一張圖像。
  • Canvas中添加Thumb 是一個(gè)可拖動(dòng)的控件,用于實(shí)現(xiàn)交互中的拖動(dòng)后獲取顏色。
<Canvas?x:Name="canvas"?MouseLeftButtonDown="canvas_MouseLeftButtonDown">
????????????????<Canvas.Background>
????????????????????<ImageBrush?ImageSource="{Binding?Bitmap}"?/>
????????????????</Canvas.Background>
????????????????<Thumb
????????????????????x:Name="thumb"
????????????????????Canvas.Left="0"
????????????????????Canvas.Top="0"
????????????????????Width="20"
????????????????????Height="20"
????????????????????Background="Transparent"
????????????????????BorderBrush="Black"
????????????????????BorderThickness="2"
????????????????????DragDelta="Thumb_DragDelta">
????????????????????<Thumb.Template>
????????????????????????<ControlTemplate?TargetType="Thumb">
????????????????????????????<Border
????????????????????????????????Background="{TemplateBinding?Background}"
????????????????????????????????BorderBrush="{TemplateBinding?BorderBrush}"
????????????????????????????????BorderThickness="{TemplateBinding?BorderThickness}"
????????????????????????????????CornerRadius="10"
????????????????????????????????SnapsToDevicePixels="True"?/>
????????????????????????</ControlTemplate>
????????????????????</Thumb.Template>
????????????????</Thumb>
????????????</Canvas>

2)新增 Loaded邏輯 處理代碼如下:

  • 首先嵌套循環(huán),用于在圖像的每個(gè)像素位置上進(jìn)行操作色值。
  • height 和 width 是圖像的高度和寬度。
  • 在外層循環(huán)中,變量 y 從 0 開始遞增,直到小于 height
  • 在內(nèi)層循環(huán)中,變量 x 從 0 開始遞增,直到小于 width
  • 在每個(gè)像素位置上,通過(guò)計(jì)算 normalizedX 和 normalizedY,將 x 和 y 的值歸一化到 [0, 1] 范圍內(nèi)。
  • 使用 HSVToRGB 函數(shù)將歸一化后的 normalizedX、normalizedY 和 1(表示最大亮度)轉(zhuǎn)換為 RGB 值,并將結(jié)果存儲(chǔ)在 r、g 和 b 變量中。
  • 計(jì)算像素在圖像數(shù)據(jù)緩沖區(qū)中的偏移量 pixelOffset,其中 stride 是每行像素占用的字節(jié)數(shù)。
  • 使用 Marshal.WriteByte 方法將 RGB 值寫入圖像數(shù)據(jù)緩沖區(qū)中的相應(yīng)位置,同時(shí)設(shè)置 Alpha 通道為 0xFF(完全不透明)。
????????????IntPtr?backBuffer?=?Bitmap.BackBuffer;
????????????int?stride?=?Bitmap.BackBufferStride;
????????????for?(int?y?=?0;?y?<?height;?y++)
????????????{
????????????????for?(int?x?=?0;?x?<?width;?x++)
????????????????{
????????????????????byte?r,?g,?b;
????????????????????double?normalizedX?=?(double)x?/?(width?-?1);
????????????????????double?normalizedY?=?(double)y?/?(height?-?1);
????????????????????HSVToRGB(normalizedX,?normalizedY,?1,?out?r,?out?g,?out?b);
????????????????????int?pixelOffset?=?y?*?stride?+?x?*?4;
????????????????????Marshal.WriteByte(backBuffer,?pixelOffset?+?0,?b);
????????????????????Marshal.WriteByte(backBuffer,?pixelOffset?+?1,?g);
????????????????????Marshal.WriteByte(backBuffer,?pixelOffset?+?2,?r);
????????????????????Marshal.WriteByte(backBuffer,?pixelOffset?+?3,?0xFF);
????????????????}
????????????}

3)新增 HSVToRGB 方法代碼如下:

  • HSVToRGB 方法返回 r 、g、b
  • h 是色相值,取值范圍為 [0, 1]。
  • s 是飽和度值,取值范圍為 [0, 1]。
  • v 是亮度值,取值范圍為 [0, 1]。
  • r、g 和 b 是輸出參數(shù),用于存儲(chǔ)轉(zhuǎn)換后的 RGB 值。
  • 在函數(shù)內(nèi)部,根據(jù) HSV 轉(zhuǎn)換公式進(jìn)行計(jì)算。如果飽和度 s 為 0,則表示灰度色調(diào),此時(shí)將 RGB 的三個(gè)分量都設(shè)置為亮度 v 的值,并乘以 255 轉(zhuǎn)換為字節(jié)表示。
  • 如果飽和度 s 不為 0,則根據(jù)色相 h 的值確定所處的色相區(qū)間,并根據(jù)公式計(jì)算出對(duì)應(yīng)的 RGB 值。具體步驟如下:
  • 將色相 h 乘以 6,得到一個(gè)擴(kuò)展的色相值 hue。
  • 取 hue 的整數(shù)部分作為索引 i,表示所處的色相區(qū)間。
  • 計(jì)算 hue 的小數(shù)部分 f。
  • 根據(jù)公式計(jì)算出對(duì)應(yīng)的 RGB 值,其中 p 是亮度 v 與飽和度 s 的乘積,q 是亮度 v 與飽和度 s 以及 f 的乘積,t 是亮度 v 與飽和度 s 以及 (1.0 - f) 的乘積。
  • 根據(jù)索引 i 的值,將計(jì)算得到的 RGB 值賦給輸出參數(shù) r、g 和 b。
private?static?void?HSVToRGB(double?h,?double?s,?double?v,?out?byte?r,?out?byte?g,?out?byte?b)
????????{
????????????if?(s?==?0)
????????????{
????????????????r?=?g?=?b?=?(byte)(v?*?255);
????????????}
????????????else
????????????{
????????????????double?hue?=?h?*?6.0;
????????????????int?i?=?(int)Math.Floor(hue);
????????????????double?f?=?hue?-?i;
????????????????double?p?=?v?*?(1.0?-?s);
????????????????double?q?=?v?*?(1.0?-?(s?*?f));
????????????????double?t?=?v?*?(1.0?-?(s?*?(1.0?-?f)));
????????????????switch?(i)
????????????????{
????????????????????case?0:
????????????????????????r?=?(byte)(v?*?255);
????????????????????????g?=?(byte)(t?*?255);
????????????????????????b?=?(byte)(p?*?255);
????????????????????????break;
????????????????????case?1:
????????????????????????r?=?(byte)(q?*?255);
????????????????????????g?=?(byte)(v?*?255);
????????????????????????b?=?(byte)(p?*?255);
????????????????????????break;
????????????????????case?2:
????????????????????????r?=?(byte)(p?*?255);
????????????????????????g?=?(byte)(v?*?255);
????????????????????????b?=?(byte)(t?*?255);
????????????????????????break;
????????????????????case?3:
????????????????????????r?=?(byte)(p?*?255);
????????????????????????g?=?(byte)(q?*?255);
????????????????????????b?=?(byte)(v?*?255);
????????????????????????break;
????????????????????case?4:
????????????????????????r?=?(byte)(t?*?255);
????????????????????????g?=?(byte)(p?*?255);
????????????????????????b?=?(byte)(v?*?255);
????????????????????????break;
????????????????????default:
????????????????????????r?=?(byte)(v?*?255);
????????????????????????g?=?(byte)(p?*?255);
????????????????????????b?=?(byte)(q?*?255);
????????????????????????break;
????????????????}
????????????}
????????}

4)新增 Thumb_DragDelta 代碼如下:

  • 在事件處理程序中,首先獲取拖動(dòng)的 Thumb 控件,并計(jì)算出新的左側(cè)和頂部位置。通過(guò) Canvas.GetLeft(thumb) 和 Canvas.GetTop(thumb) 方法獲取當(dāng)前 Thumb 控件在 Canvas 中的左側(cè)和頂部位置,然后將其與拖動(dòng)的變化量 e.HorizontalChange 和 e.VerticalChange 相加,得到新的位置。
  • 計(jì)算 Canvas 的右側(cè)和底部邊界。通過(guò) canvas.ActualWidth - thumb.ActualWidth 和 canvas.ActualHeight - thumb.ActualHeight 計(jì)算出 Canvas 的右側(cè)和底部邊界位置。
  • 對(duì)新的左側(cè)和頂部位置進(jìn)行邊界檢查。如果新的左側(cè)位置小于 0,則將其設(shè)置為 0,以保證 Thumb 控件不會(huì)超出 Canvas 的左側(cè)邊界。如果新的左側(cè)位置大于 Canvas 的右側(cè)邊界位置 canvasRight,則將其設(shè)置為 canvasRight,以確保 Thumb 控件不會(huì)超出 Canvas 的右側(cè)邊界。類似地,對(duì)新的頂部位置進(jìn)行邊界檢查。
  • 通過(guò) Canvas.SetLeft(thumb, newLeft) 和 Canvas.SetTop(thumb, newTop) 將 Thumb 控件的位置更新為新的左側(cè)和頂部位置。
  • 調(diào)用 GetAreaColor() 方法來(lái)獲取更新后的區(qū)域顏色。
?private?void?Thumb_DragDelta(object?sender,?DragDeltaEventArgs?e)
????????{
????????????var?thumb?=?(Thumb)sender;
????????????double?newLeft?=?Canvas.GetLeft(thumb)?+?e.HorizontalChange;
????????????double?newTop?=?Canvas.GetTop(thumb)?+?e.VerticalChange;
????????????double?canvasRight?=?canvas.ActualWidth?-?thumb.ActualWidth;
????????????double?canvasBottom?=?canvas.ActualHeight?-?thumb.ActualHeight;
????????????if?(newLeft?<?0)
????????????????newLeft?=?0;
????????????else?if?(newLeft?>?canvasRight)
????????????????newLeft?=?canvasRight;
????????????if?(newTop?<?0)
????????????????newTop?=?0;
????????????else?if?(newTop?>?canvasBottom)
????????????????newTop?=?canvasBottom;
????????????Canvas.SetLeft(thumb,?newLeft);
????????????Canvas.SetTop(thumb,?newTop);
????????????GetAreaColor();
????????}

5)新增 canvas_MouseLeftButtonDown 代碼如下:

實(shí)現(xiàn)鼠標(biāo)左鍵按下時(shí),將 Thumb 控件移動(dòng)到鼠標(biāo)點(diǎn)擊位置,并進(jìn)行邊界限制。同時(shí),還獲取了鼠標(biāo)點(diǎn)擊位置的顏色信息

?private?void?canvas_MouseLeftButtonDown(object?sender,?MouseButtonEventArgs?e)
????????{
????????????var?canvasPosition?=?e.GetPosition(canvas);
????????????double?newLeft?=?canvasPosition.X?-?thumb.ActualWidth?/?2;
????????????double?newTop?=?canvasPosition.Y?-?thumb.ActualHeight?/?2;
????????????double?canvasRight?=?canvas.ActualWidth?-?thumb.ActualWidth;
????????????double?canvasBottom?=?canvas.ActualHeight?-?thumb.ActualHeight;
????????????if?(newLeft?<?0)
????????????????newLeft?=?0;
????????????else?if?(newLeft?>?canvasRight)
????????????????newLeft?=?canvasRight;
????????????if?(newTop?<?0)
????????????????newTop?=?0;
????????????else?if?(newTop?>?canvasBottom)
????????????????newTop?=?canvasBottom;
????????????Canvas.SetLeft(thumb,?newLeft);
????????????Canvas.SetTop(thumb,?newTop);
????????????var?thumbPosition?=?e.GetPosition(canvas);
????????????GetAreaColor(thumbPosition);
????????}

6)新增 GetAreaColor 代碼如下:

Thumb 控件的中心點(diǎn)坐標(biāo)轉(zhuǎn)換為相對(duì)于 Canvas 的坐標(biāo)。

計(jì)算每行像素?cái)?shù)據(jù)所占的字節(jié)數(shù)。

創(chuàng)建一個(gè)字節(jié)數(shù)組,用于存儲(chǔ)位圖的像素?cái)?shù)據(jù)。

將位圖的像素?cái)?shù)據(jù)復(fù)制到字節(jié)數(shù)組中。

計(jì)算要訪問(wèn)的像素在字節(jié)數(shù)組中的索引位置。

Color.FromArgb取其 Alpha、紅色、綠色和藍(lán)色通道的值。在這段代碼中,它被用于構(gòu)造一個(gè) Color 對(duì)象,表示位圖中特定像素的顏色。

  • pixels[pixelIndex + 3] 表示字節(jié)數(shù)組中的第 pixelIndex + 3 個(gè)元素,即 Alpha 通道的值。
  • pixels[pixelIndex + 2] 表示字節(jié)數(shù)組中的第 pixelIndex + 2 個(gè)元素,即紅色通道的值。
  • pixels[pixelIndex + 1] 表示字節(jié)數(shù)組中的第 pixelIndex + 1 個(gè)元素,即綠色通道的值。
  • pixels[pixelIndex] 表示字節(jié)數(shù)組中的第 pixelIndex 個(gè)元素,即藍(lán)色通道的值。
?void?GetAreaColor(Point??thumbPosition?=?null)
????????{
????????????thumbPosition?=?thumbPosition?==?null???thumbPosition?=?thumb.TranslatePoint(new?Point(thumb.ActualWidth?/?2,?thumb.ActualHeight?/?2),?canvas)?:?thumbPosition;
????????????int?xCoordinate?=?(int)thumbPosition?.X;
????????????int?yCoordinate?=?(int)thumbPosition?.Y;
????????????if?(xCoordinate?>=?0?&&?xCoordinate?<?Bitmap.PixelWidth?&&?yCoordinate?>=?0?&&?yCoordinate?<?Bitmap.PixelHeight)
????????????{
????????????????int?stride?=?Bitmap.PixelWidth?*?(Bitmap.Format.BitsPerPixel?/?8);
????????????????byte[]?pixels?=?new?byte[Bitmap.PixelHeight?*?stride];
????????????????Bitmap.CopyPixels(new?Int32Rect(0,?0,?Bitmap.PixelWidth,?Bitmap.PixelHeight),?pixels,?stride,?0);
????????????????int?pixelIndex?=?(yCoordinate?*?stride)?+?(xCoordinate?*?(Bitmap.Format.BitsPerPixel?/?8));
????????????????Color?color?=?Color.FromArgb(pixels[pixelIndex?+?3],?pixels[pixelIndex?+?2],?pixels[pixelIndex?+?1],?pixels[pixelIndex]);
????????????????MyBtn.Background?=?new?SolidColorBrush(color);
????????????}
????????}

效果圖

到此這篇關(guān)于基于WPF開發(fā)簡(jiǎn)單的顏色選擇器的文章就介紹到這了,更多相關(guān)WPF顏色選擇器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論