介绍

最近一直在研究Flutter,但是在创建UI的时候经常想获取屏幕上的颜色。
在这种情况下,我想要一个可以轻松获取颜色信息的软件,所以我做了它。
如果需要,可以从本文底部下载。
下面是哪种应用程序的图像

嵌入 Qiita 的视频
我在 C# 中制作了一个具有零个不必要功能的颜色选择器皮c。山雀河。这个 m/jo M0D q9P

— 鱿鱼 (@ika_kk)2022 年 8 月 10 日

背景

我尝试了各种方法来获取颜色,但我找不到适合我的方法...

  • 截图 + Photoshop
    我一开始也是这样做的,但是太麻烦了
  • 画 3d
    我可以做我想做的,但毕竟有很多准备工作
  • 只是颜色选择器
    优秀的软件。没有比这更好的了,不是吗?
    然而,窗口尺寸有点大,这是球的一个缺陷,我有时认为这是一个障碍。

似乎还有很多其他的东西,但我决定在学习的同时尝试自己制作。

这个应用程序的特点

这很简单。

①可指定提取尺寸

这是特色功能。
在提取精确像素颜色时,由于噪声的影响,它变得相当不均匀,因此我们可以指定提取范围。
换言之,当增加提取范围时,获取范围内的平均颜色信息。
这可以在一定程度上抵消噪音的影响。
シンプルなカラーピッカーを作りました【配布してます】
但是,监视器区域的外部似乎是黑色的(#000000),当提取尺寸较大并提​​取显示器边缘附近的区域时,颜色可能会变暗一些。在这种情况下,请缩小提取大小并采取对策。

② 可以得到色码/RGB/HSB/灰度值

除了常用的色码(#RRGGBB)和RGB值,还可以得到HSV值和灰度值转换为灰度。

关于 HSV,所需的值范围因使用的场景而异,因此可以指定。
H 为 0~360 或 0~255,S 和 V 为 0~255 或 0~100。
根据要使用的场景指定单选按钮。

按照我常用的标准电视播放标准,灰度值为0.3R+0.59G+0.11B。

③其他特点

我觉得可以随时看到颜色信息会很方便,所以我将它设置为始终显示在屏幕的最前面。
另外,我尝试删除标题栏以使其看起来很酷。
可以通过拖动适当的位置来调整位置。
(WPF) 尝试实现一个时尚的半透明窗口 - Mame - Tantanmen
シンプルなカラーピッカーを作りました【配布してます】

技术故事

如何获取屏幕上的像素值

这是这个应用程序的关键部分。我实现了像素提取如下。
第 8 到 11 行 graphics.CopyFromScreen(...) 提取屏幕的任意位置和大小。

  • 参数 1:提取范围的左上角坐标。指定从当前光标位置减去直径/2=半径的点。
  • 参数 2:写入位图时的起始坐标。指定位图的左上角 = (0, 0)。
  • 参数 3:提取范围的大小。指定直径。
捕获光标周围的实现部分
// サーチ直径
int _diam;

while (true)
{
    // 現在のカーソル位置周辺の画像取得
    var bitmap = new Bitmap(_diam, _diam);
    var currentPos = System.Windows.Forms.Cursor.Position;
    using (var graphic = Graphics.FromImage(bitmap))
    {
        graphic.CopyFromScreen(
            new System.Drawing.Point(currentPos.X - _diam / 2, currentPos.Y - _diam / 2),
            new System.Drawing.Point(0, 0),
            new System.Drawing.Size(_diam, _diam));
    }
    // 変数bitmapには、現在のカーソル周辺をキャプチャした画像が入ります。
    // 以降その画像をよしなにして平均値を取得し、画面に表示しています。         
}

我相信你们中的一些人已经注意到了,所以我承认。
虽然宣传是取圆圈内的平均值,但实际上取的是正方形内的平均值。
圈内判断很麻烦这是一个温柔的谎言,不是吗?
请原谅我,因为无论是圆形还是方形,结果可能都没有太大变化。
シンプルなカラーピッカーを作りました【配布してます】

关于提取大小和处理时间

我认为如果提取尺寸很大,则需要时间来获得平均值,所以我测量了它。

实验环境
Windows10, Core i7-6700(x64), RAM16GB, GeForceGTX960, 60fps 显示器
实验条件
一边摇动萃取范围的水平一边测量 1,000 次。
让我们看一下平均值。

シンプルなカラーピッカーを作りました【配布してます】
对于 $N$ 的搜索直径,我预计处理时间会增加 $O(N^2)$,但它会在 256px 的直径下保持 60fps。
超过512px,它是二次增长的,但我并没有真正使用这么大的半径,所以它应该不是问题。
(特别是这次实现的上限是32px)
我用调试监视器检查了 CPU 使用率和内存。
CPU 使用率没有明显变化,32px 的内存最大约为 100MB。

完整代码

我把它上传到 GitHub,但现在。

  • 语言 C# / .NET Framework 4.8
  • 编辑器 Visual Studio Community 2017 版本 15.7.4
  • 我不使用任何特殊库,基本上是原生编写的
后面的代码
主窗口.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ColorPickerPj
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>サーチ半径を保持する変数</summary>
        private int _diam = 1;

        /// <summary>
        /// コンストラクタ。
        /// プログラム実行と同時に色取得処理を開始する。
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            // ウインドウ半透明にしたときにドラッグできるようにする
            // 以下参考URL
            // https://p4j4.hatenablog.com/entry/2018/03/31/170251
            MouseLeftButtonDown += (_,__) => { DragMove(); };
            
            // メインループ
            var task = new Task(MainLoop);
            task.Start();
        }

        /// <summary>
        /// プログラム実行中まわりつづけるループ。
        /// 常に現在のカーソル周辺の画素値を分析しつづける。
        /// タスクとして使用。
        /// </summary>
        private void MainLoop()
        {
            while (true)
            {
                // 現在のカーソル位置周辺の画像取得
                var bitmap = new Bitmap(_diam, _diam);
                var currentPos = System.Windows.Forms.Cursor.Position;
                using (var graphic = Graphics.FromImage(bitmap))
                {
                    graphic.CopyFromScreen(
                        new System.Drawing.Point(currentPos.X - _diam / 2, currentPos.Y - _diam / 2),
                        new System.Drawing.Point(0, 0),
                        new System.Drawing.Size(_diam, _diam));
                }
                // デバッグ用
                //bitmap.Save("temp.bmp");

                // 画素値(RGB)取得
                byte r, g, b;
                GetMeanValueFromBitmap(bitmap, out r, out g, out b);

                // HSVへ変換
                double h, s, v;
                RgbToHsv(r, g, b, out h, out s, out v);

                // グレースケール値
                byte gray = (byte)(0.30 * r + 0.59 * g + 0.11 * b);

                // 表示更新
                // 実際にはHSVも同時に計算して表示する
                var msg = new Action<byte, byte, byte, double, double, double, byte>(UpdateValue);
                Dispatcher.Invoke(msg, r, g, b, h, s, v, gray);
                
            }
        }

        /// <summary>
        /// 画像の各チャンネルの平均画素値を取得する。
        /// 下記参考URL
        /// https://www.84kure.com/blog/2014/07/13/c-%E3%83%93%E3%83%83%E3%83%88%E3%83%9E%E3%83%83%E3%83%97%E3%81%AB%E3%83%94%E3%82%AF%E3%82%BB%E3%83%AB%E5%8D%98%E4%BD%8D%E3%81%A7%E9%AB%98%E9%80%9F%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9/
        /// </summary>
        /// <param name="bitmap">入力画像。デフォルトは32bitARGBのはず。</param>
        /// <param name="r">Rチャンネルの平均画素値</param>
        /// <param name="g">Gチャンネルの平均画素値</param>
        /// <param name="b">Bチャンネルの平均画素値</param>
        private void GetMeanValueFromBitmap(Bitmap bitmap, out byte r, out byte g, out byte b)
        {
            BitmapData data = bitmap.LockBits(
                new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadWrite,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            // リストに画素値を格納していく。byte型だと平均が出せないのでdouble型でやる。
            var rValues = new List<double>();
            var gValues = new List<double>();
            var bValues = new List<double>();
            int bytes = bitmap.Width * bitmap.Height * 4;
            for (int i = 0; i < bytes; i += 4)
            {
                bValues.Add(Marshal.ReadByte(data.Scan0, i));
                gValues.Add(Marshal.ReadByte(data.Scan0, i + 1));
                rValues.Add(Marshal.ReadByte(data.Scan0, i + 2));
            }
            bitmap.UnlockBits(data);

            // なんかの拍子に格納されてなかったら怖いので一応条件分岐
            if (rValues.Count > 0 && gValues.Count > 0 && bValues.Count > 0)
            {
                r = (byte)rValues.Average();
                g = (byte)gValues.Average();
                b = (byte)bValues.Average();
            }
            else
            {
                r = g = b = 0;
            }
        }

        /// <summary>
        /// RGBをHSVに変換する。
        /// Hは0~360、sとvは0~255で取得する。
        /// </summary>
        /// <param name="r">R値</param>
        /// <param name="g">G値</param>
        /// <param name="b">B値</param>
        /// <param name="h">H値。0~360</param>
        /// <param name="s">S値。0~255</param>
        /// <param name="v">V値。0~255</param>
        private void RgbToHsv(byte r, byte g, byte b, out double h, out double s, out double v)
        {
            double max = Math.Max(r, Math.Max(g, b));
            double min = Math.Min(r, Math.Min(g, b));

            // 色相
            if (r == g && g == b)
            {
                h = 0;
            }
            else if (r >= g && r >= b)
            {
                h = 60.0 * ((double)(g - b) / (max - min));
            }
            else if (g >= r && g >= b)
            {
                h = 60.0 * ((double)(b - r) / (max - min)) + 120;
            }
            else
            {
                h = 60.0 * ((double)(r - g) / (max - min)) + 240;
            }
            if (h < 0)
            {
                h += 360;
            }

            // 彩度
            if (max == 0)
            {
                s = 0;
            }
            else
            {
                s = (max - min) / max;
                s *= 255;
            }

            // 明度
            v = max;
        }

        /// <summary>
        /// RGB値とHSV値をもとに画面表示を更新する。
        /// HSVに関しては画面の設定をもとに値域を変換する。
        /// </summary>
        /// <param name="r">R値</param>
        /// <param name="g">G値</param>
        /// <param name="b">B値</param>
        /// <param name="h">H値。0~360</param>
        /// <param name="s">S値。0~255</param>
        /// <param name="v">V値。0~255</param>
        /// <param name="gray">グレースケール値</param>
        private void UpdateValue(byte r, byte g, byte b, double h, double s, double v, byte gray)
        {
            // サーチ直径の表示色を見えやすい色に設定
            brushEllipse.Stroke = v < 128 ?
                new SolidColorBrush(System.Windows.Media.Color.FromArgb(200, 200, 200, 200)):   // 背景が暗い場合は白線
                new SolidColorBrush(System.Windows.Media.Color.FromArgb(200,  55,  55,  55));   // 背景が明るい場合は黒線

            // hsvの値域を調整
            if (h255RadioButton.IsChecked == true) h = (byte)(h * 255.0 / 360.0);
            if (s100RadioButton.IsChecked == true) s = (byte)(s * 100.0 / 255.0);
            if (v100RadioButton.IsChecked == true) v = (byte)(v * 100.0 / 255.0);

            // 値更新
            string code = $"#{r.ToString("X2")}{g.ToString("X2")}{b.ToString("X2")}";
            colorCodeTextBox.Text = code;
            rTextBox.Text = r.ToString();
            gTextBox.Text = g.ToString();
            bTextBox.Text = b.ToString();
            hTextBox.Text = ((int)h).ToString();
            sTextBox.Text = ((int)s).ToString();
            vTextBox.Text = ((int)v).ToString();
            grayTextBox.Text = gray.ToString();
            colorRectangle.Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(r, g, b));
        }


        /// <summary>
        /// マウスホイールでスライダーを制御するイベント。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void diamSlider_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (e.Delta > 0)
            {
                diamSlider.Value++;
            }
            else if (e.Delta < 0)
            {
                diamSlider.Value--;
            }
        }

        /// <summary>
        /// スライダーの値をもとにサーチ半径表示を更新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void diamSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            _diam = (int)diamSlider.Value;
            diamTextBlock.Text = $"{_diam} px";
            brushEllipse.Width = brushEllipse.Height = _diam + 2;
        }
        
        /// <summary>
        /// 終了イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void closeButton_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
        
    }
}
用户界面 (XAML)
主窗口.xaml
<Window x:Class="ColorPickerPj.MainWindow"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ColorPickerPj"
        mc:Ignorable="d"
        Title="MainWindow" Height="165.201" Width="363.467" Topmost="True" SizeToContent="WidthAndHeight" Background="#E6444444"
        x:Name="mainWindow" WindowStyle="None" AllowsTransparency="True">


    <Window.Resources>

        <Style TargetType="TextBlock" x:Key="normalTextBlock">
            <Setter Property="Foreground" Value="#FFCCCCCC"/>
        </Style>

        <Style TargetType="TextBlock" x:Key="valueTextBlock">
            <Setter Property="Foreground" Value="#FFCCCCCC"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Setter Property="Margin" Value="0,0,5,0"/>
        </Style>

        <Style TargetType="RadioButton">
            <Setter Property="Foreground" Value="#FFCCCCCC"/>
            <Setter Property="FontSize" Value="9"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
        </Style>

        <!-- 通常時のボタンの色 -->
        <SolidColorBrush x:Key="NormalButtonBrush" Color="Transparent"/>
        <!-- 通常時のボタンの背景色 -->
        <SolidColorBrush x:Key="NormalBackgroundBrush" Color="Transparent"/>
        <!-- マウスオーバー時のボタンの色 -->
        <SolidColorBrush x:Key="HoverButtonBrush" Color="Transparent"/>
        <!-- マウスオーバー時のボタンの背景色 -->
        <SolidColorBrush x:Key="HoverBackgroundBrush" Color="Transparent"/>
        <!-- カスタムボタンのスタイル -->
        <Style x:Key="HoverButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="{StaticResource NormalButtonBrush}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Name="HoverButtonBorder" BorderThickness="2" BorderBrush="{StaticResource NormalButtonBrush}" Background="{StaticResource NormalBackgroundBrush}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <!-- マウスオーバー -->
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="HoverButtonBorder" Property="BorderBrush" Value="{StaticResource HoverButtonBrush}" />
                                <Setter TargetName="HoverButtonBorder" Property="Background" Value="{StaticResource HoverBackgroundBrush}" />
                                <Setter Property="Foreground" Value="{StaticResource HoverButtonBrush}"/>
                            </Trigger>
                            <!-- ボタンを押した時に、背景色を透過 -->
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="HoverButtonBorder" Property="Background" Value="{StaticResource NormalBackgroundBrush}" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>


    </Window.Resources>

    <Grid Margin="5">

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="72"/>
                <RowDefinition Height="50"/>
            </Grid.RowDefinitions>

            <!-- 中段 -->
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="120px"/>
                    <ColumnDefinition Width="72px"/>
                    <ColumnDefinition Width="120px"/>
                </Grid.ColumnDefinitions>

                <!-- 色情報表示部(文字) -->
                <Grid Grid.Column="0" Margin="3">
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="2.5*"/>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="2.5*"/>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="2.5*"/>
                    </Grid.ColumnDefinitions>

                    <TextBlock Style="{StaticResource normalTextBlock}" x:Name="colorCodeTextBox" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6" Text="#xxxxxx" TextAlignment="Center"/>
                    <TextBlock Style="{StaticResource normalTextBlock}" Grid.Row="1" Grid.Column="0" Text="R" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="#FFCC8F8F"/>
                    <TextBlock Style="{StaticResource normalTextBlock}" Grid.Row="1" Grid.Column="2" Text="G" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="#FF90CC8F"/>
                    <TextBlock Style="{StaticResource normalTextBlock}" Grid.Row="1" Grid.Column="4" Text="B" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="#FF8F96EE"/>
                    <TextBlock Style="{StaticResource valueTextBlock}" x:Name="rTextBox" Grid.Row="1" Grid.Column="1"/>
                    <TextBlock Style="{StaticResource valueTextBlock}" x:Name="gTextBox" Grid.Row="1" Grid.Column="3"/>
                    <TextBlock Style="{StaticResource valueTextBlock}" x:Name="bTextBox" Grid.Row="1" Grid.Column="5"/>
                    <TextBlock Style="{StaticResource normalTextBlock}" Grid.Row="2" Grid.Column="0" Text="H" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    <TextBlock Style="{StaticResource normalTextBlock}" Grid.Row="2" Grid.Column="2" Text="S" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    <TextBlock Style="{StaticResource normalTextBlock}" Grid.Row="2" Grid.Column="4" Text="V" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    <TextBlock Style="{StaticResource valueTextBlock}" x:Name="hTextBox" Grid.Row="2" Grid.Column="1"/>
                    <TextBlock Style="{StaticResource valueTextBlock}" x:Name="sTextBox" Grid.Row="2" Grid.Column="3"/>
                    <TextBlock Style="{StaticResource valueTextBlock}" x:Name="vTextBox" Grid.Row="2" Grid.Column="5"/>

                    <StackPanel Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6" Orientation="Horizontal">
                        <TextBlock Style="{StaticResource normalTextBlock}" Text="Grayscale " VerticalAlignment="Center"/>
                        <TextBlock Style="{StaticResource valueTextBlock}" x:Name="grayTextBox"/>
                    </StackPanel>
                    
                </Grid>

                <!-- 色情報表示部(色) -->
                <Grid Grid.Column="1" Margin="3">
                    <Rectangle x:Name="colorRectangle" Fill="#FF123456" RadiusX="16" RadiusY="16"/>
                    <Ellipse x:Name="brushEllipse" Stroke="Black"/>
                </Grid>

                <!-- サーチ直径調整部 -->
                <Grid Grid.Column="2" Margin="3">
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <StackPanel Orientation="Horizontal" Grid.Row="0">
                        <TextBlock Style="{StaticResource normalTextBlock}" Text="サーチ直径 "/>
                        <TextBlock Style="{StaticResource normalTextBlock}" x:Name="diamTextBlock" Text="diam px"/>
                    </StackPanel>
                    <Slider x:Name="diamSlider" Grid.Row="2" Minimum="1" Maximum="32"
                    IsSnapToTickEnabled="True" TickFrequency="1" LargeChange="8"
                        ValueChanged="diamSlider_ValueChanged" MouseWheel="diamSlider_MouseWheel" Value="1"/>

                </Grid>
            </Grid>

            <!-- 下段 -->
            <Grid Grid.Row="1" Margin="3" Width="150" HorizontalAlignment="Left">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Row="0" Grid.Column="0" Text="Hの値域" Style="{StaticResource normalTextBlock}" FontSize="9" VerticalAlignment="Center"/>
                <TextBlock Grid.Row="1" Grid.Column="0" Text="Sの値域" Style="{StaticResource normalTextBlock}" FontSize="9" VerticalAlignment="Center"/>
                <TextBlock Grid.Row="2" Grid.Column="0" Text="Vの値域" Style="{StaticResource normalTextBlock}" FontSize="9" VerticalAlignment="Center"/>

                <RadioButton x:Name="h360RadioButton" Grid.Row="0" Grid.Column="1" Content="0-360" GroupName="groupH" IsChecked="True"/>
                <RadioButton x:Name="h255RadioButton" Grid.Row="0" Grid.Column="2" Content="0-255" GroupName="groupH"/>

                <RadioButton x:Name="s255RadioButton" Grid.Row="1" Grid.Column="1" Content="0-255" GroupName="groupS" IsChecked="True"/>
                <RadioButton x:Name="s100RadioButton" Grid.Row="1" Grid.Column="2" Content="0-100" GroupName="groupS"/>

                <RadioButton x:Name="v255RadioButton" Grid.Row="2" Grid.Column="1" Content="0-255" GroupName="groupV" IsChecked="True"/>
                <RadioButton x:Name="v100RadioButton" Grid.Row="2" Grid.Column="2" Content="0-100" GroupName="groupV"/>


            </Grid>

            <!-- 終了ボタン -->
            <!-- マウスオーバー時透明 参考 http://gootara.org/library/2016/07/wpf-hvr.html -->
            <Button x:Name="closeButton" Grid.Row="2" HorizontalAlignment="Right" Width="50" Margin="3" Cursor="Hand"
                    Click="closeButton_Click" Style="{StaticResource HoverButtonStyle}">
                <Image Source="Resource/close_icon.png" RenderOptions.BitmapScalingMode="HighQuality">
                    <Image.Effect>
                        <DropShadowEffect BlurRadius="20" RenderingBias="Quality" ShadowDepth="0"/>
                    </Image.Effect>
                </Image>
                <ToolTipService.ToolTip>
                    <ToolTip Content="カラーピッカーを終了します"/>
                </ToolTipService.ToolTip>
            </Button>

        </Grid>
    </Grid>
    
</Window>

下载

我将源代码和 exe(软件主体)上传到 GitHub。

我只在我自己的环境中调试过它,但由于它是本机实现的,它应该在 Windows 10 或更高版本上运行良好。
但是,由于我没有设置任何东西就写了,我认为会出现警告,但可以通过以下方法执行。
当然,我没有编写任何恶意代码,但请您自担风险。
(有人请告诉我如何进行数字签名......)
シンプルなカラーピッカーを作りました【配布してます】

综上所述

其实功能多点可能更好,但我决定做一些简单的事情,所以我放弃了各种各样的东西。

  • 颜色代码复制功能...是否可以使用快捷方式?
  • 调色板建议功能...建议具有相同饱和度的颜色
  • XY 坐标显示...有时我想要坐标值。这可以实施吗?

结果,我认为创建了一个相当易于使用的颜色选择器,
我能够实现我想要轻松查看大部分颜色信息的最初目的,所以我对此很满意。
如果您不介意,请使用它。

就这样


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308623819.html

相关文章:

  • 2021-07-26
  • 2021-12-01
  • 2021-11-07
  • 2022-01-08
  • 2022-12-23
  • 2021-10-22
  • 2021-05-22
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-01-13
  • 2022-12-23
  • 2021-06-09
  • 2022-12-23
  • 2021-08-15
相关资源
相似解决方案