6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

コピペで使えるGUIカラーピッカー(Powershell)を作った【インストール不要】

Posted at

日常の業務にて画面上のRGB色を取りたいという機会があったのですが、勝手にフリーソフト等をインストールできる環境ではなかったので、簡単に利用できるカラーピッカーGUIがあればなぁということで少し作ってみたという記事になります。

機能概要

image.png

  • F4キーでマウスカーソルにある色を取得可能(Hex, RGBの欄に値がセットされる)
  • 取得したRGB,Hexをクリップボードにコピーする
  • 履歴機能 (F4を押すと自動で履歴に追加される)
    など

注意点

  • それぞれDPIが異なるマルチディスプレイ環境だとカーソル位置から上手く色を取得できないかもしれません。
  • Windows10, 11以外では動作させていません。

起動手順

  1. 記事最下部のソースコード(250行程度)をコピー
  2. テキストファイルに保存して実行する (拡張子は.ps1)

起動時のコンソールが邪魔な場合

powershellのGUIソフトは起動するとコンソールもおまけで表示されてしまうらしいため、それが嫌な場合は下記コマンド経由で起動すれば自動でコンソールが最小化されて起動されます。

powershell -WindowStyle Minimized  -File ./color_picker.ps1

またこれを.batのファイルに保存しておけば、それ経由でアプリを起動することも可能ですし、またExecutionPolicy周りのエラーも回避できると思います。

ソースコード(Powershell)

下記からコピペお願い致します。
ちなみにWinFormsではなくWPFを使用しています。

Set-StrictMode -Version Latest

$assemblies = @(
    "PresentationFramework"
    "System.Windows.Forms"
    "System.Drawing"
)

Add-Type -AssemblyName $assemblies


function New-ControlFromXaml
{
    param (
        [xml]$xaml
    )
    $reader = [System.Xml.XmlNodeReader]::new($xaml)
    $window = [System.Windows.Markup.XamlReader]::Load($reader)
    return $window
}


$windowXaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Color Picker"
  Width="500"
  Height="365"
  ResizeMode="NoResize"
  WindowStartupLocation="CenterScreen"
  Topmost="True"
  
  FontFamily="メイリオ">

  <Window.Resources>
    
  </Window.Resources>

  <DockPanel>
    
    <Label DockPanel.Dock="Bottom" Content="※F4キーでカーソル位置の色を取得"/>
    
    <Grid Margin="5">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <!-- 1行目 -->
        <Label
            Grid.Row="0"
            Grid.Column="0"
            Content="Hex"
            />
        <TextBox
            Name="txt_hex"
            Grid.Row="0"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            Text="#FFFFFF"
            />
        <Button
            Name="btn_hex"
            Grid.Row="0"
            Grid.Column="3"
            Margin="10 0 0 0"
            Content="Copy"
            />

        <!-- 2行目 -->
        <Label
            Grid.Row="1"
            Grid.Column="0"
            Content="RGB"
            />
        <TextBox
            Name="txt_rgb"
            Grid.Row="1"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            Text="RGB(255, 255, 255)"
            />
        <Button
            Name="btn_rgb"
            Grid.Row="1"
            Grid.Column="3"
            Margin="10 0 0 0"
            Content="Copy"
            />

        <!-- 3行目 -->
        <Label
            Grid.Row="2"
            Grid.Column="0"
            Content="Preview"
            />
        <Border
            Name="bdr_preview"
            Grid.Row="2"
            Grid.Column="1"
            BorderThickness="1"
            BorderBrush="Black"
            />

        <!-- 4行目 -->
        <Label
            Grid.Row="3"
            Grid.Column="0"
            Content="History"
            />
        <Button
            Name="btn_removeHistory"
            Grid.Row="3"
            Grid.Column="1"
            Content="Remove"
            Margin="0 5 0 5"
            />

        <!-- 5行目 -->
        <ListView
            Name="lsv_history"
            Grid.Row="4"
            Grid.Column="0"
            Grid.ColumnSpan="4">

            <ListView.View>
                <GridView>
                    <GridViewColumn Header="HEX" Width="80" DisplayMemberBinding="{Binding Hex}"/>
                    <GridViewColumn Header="RGB" Width="150" DisplayMemberBinding="{Binding Rgb}"/>
                    <GridViewColumn Header="Preview" Width="70">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Border BorderThickness="1" BorderBrush="Black" Height="10" Width="10" Background="{Binding Hex}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Note" Width="160">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBox Width="149" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>

        </ListView>

    </Grid>
  </DockPanel>

</Window>
"@


# RGB取得処理
function Get-ColorFromCursor() {
    $bitmap = New-Object System.Drawing.Bitmap(1, 1)
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap)

    $dpiScaling = 1.0
    $positionX = [System.Windows.Forms.Cursor]::Position.X * $dpiScaling
    $positionY = [System.Windows.Forms.Cursor]::Position.Y * $dpiScaling

    # カーソルの位置のスクリーンの RGB 値を取得
    $graphics.CopyFromScreen($positionX, $positionY, 0, 0, $bitmap.Size)
    $pixel = $bitmap.GetPixel(0, 0)
    
    $result = @{
        "rgb" = "RGB({0}, {1}, {2})"  -f $pixel.R, $pixel.G, $pixel.B
        "hex" = "#{0:X2}{1:X2}{2:X2}" -f $pixel.R, $pixel.G, $pixel.B
    }

    return $result
}

# Main処理
if ($MyInvocation.InvocationName -ne ".")
{
    $window = New-ControlFromXaml $windowXaml
    
    $script:bdr_preview = $window.FindName("bdr_preview")
    $script:txt_rgb     = $window.FindName("txt_rgb")
    $script:btn_rgb     = $window.FindName("btn_rgb")
    $script:txt_hex     = $window.FindName("txt_hex")
    $script:btn_hex     = $window.FindName("btn_hex")
    $script:lsv_history = $window.FindName("lsv_history")
    $script:btn_removeHistory = $window.FindName("btn_removeHistory")

    $window.Add_KeyDown({
        $sender, $e = $this, $_

        if ($e.key -eq "F4")
        {
            $color = Get-ColorFromCursor
            $script:bdr_preview.Background = $color.hex

            $script:txt_rgb.Text = $color.rgb
            $script:txt_hex.Text = $color.hex

            $script:lsv_history.Items.Insert(0, [PSCustomObject]@{"Hex"=$color.hex; "Rgb"=$color.rgb;})
            # 先頭にスクロール
            $script:lsv_history.ScrollIntoView($script:lsv_history.Items[0])
        }
    })

    $script:btn_rgb.Add_Click({
        Set-Clipboard $script:txt_rgb.Text
    })

    $script:btn_hex.Add_Click({
        Set-Clipboard $script:txt_hex.Text
    })
    $script:btn_removeHistory.Add_Click({
        $lsv_history.Items.RemoveAt($lsv_history.SelectedIndex)
    })

    $script:lsv_history.Add_SelectionChanged({
        $color = $script:lsv_history.SelectedItem
        if ($color -eq $null) { return }
        $rgb   = $color.Rgb
        $hex   = $color.Hex
        $script:txt_rgb.Text = $rgb
        $script:txt_hex.Text = $hex
        $script:bdr_preview.Background = $color.Hex
    })

    $window.Add_ContentRendered({
        
    })

    $window.Add_Closing({
    
    })

    $window.ShowDialog() > $null

}

以上です

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?