winformspowershellcolorshighlightsystemcolors

Changing System Colors


Thank you for taking the time to help me.

I am using PowerShell to build a GUI and I would like to override default system colors.

For example, when a control is highlighted (TextBox or ComboBox), form shows system colors. I would like to change the color to use AliceBlue. So far I have tried following codes, but to no avail:

[System.Drawing.SystemColors]::Highlight = 'AliceBlue'
[System.Drawing.SystemColors]::HighlightText = 'AliceBlue'
[System.Drawing.SystemColors]::ScrollBar = 'AliceBlue'
[System.Drawing.SystemColors]::Control = 'AliceBlue'
[System.Drawing.SystemColors]::HotTrack = 'AliceBlue'
[System.Drawing.SystemColors]::Window = 'AliceBlue'
[System.Drawing.SystemColors]::WindowFrame = 'AliceBlue'

Solution

  • The documentation says that those properties you are trying to set are readonly.

    You can do this by invoking the user32.dll SetSysColors function:

    $signature = @'
    [DllImport("user32.dll")]
    public static extern bool SetSysColors(
        int cElements, 
        int [] lpaElements,
        uint [] lpaRgbValues);
    '@
    
    $type = Add-Type -MemberDefinition $signature `
                     -Name Win32Utils `
                     -Namespace SetSysColors `
                     -PassThru
    
    $color = [Drawing.Color]::AliceBlue
    # For RGB color values: 
    # $color = [Drawing.Color]::FromArgb(255,255,255) 
    $elements = @('13')
    $colors = [Drawing.ColorTranslator]::ToWin32($color)
    
    $type::SetSysColors($elements.Length, $elements, $colors)
    

    Where the 13 element represents COLOR_HIGHLIGHT, which is the colour of an item selected in a control.


    After running the above code, here is the result:

    ComboBox

    enter image description here

    TextBox

    enter image description here


    You can see that the colour of the actual text has changed and it is barely visible. To change this, simply run:

    $color = [Drawing.Color]::Black
    $elements = @('14')
    $colors = [Drawing.ColorTranslator]::ToWin32($color)
    $type::SetSysColors($elements.Length, $elements, $colors)
    

    Where 14 represents COLOR_HIGHLIGHTTEXT, which is the colour of the text of an item selected in a control.

    To see more about SetSysColors check PInvoke. Also, go here to find more color codes.


    I don't know if it is possible to set the highlight colour for only the PowerShell GUI and nothing else using WinForms or SetSysColor, but one way you might consider is by using a WPF TextBox instead of WinForms. This way you can use SelectionBrush and SelectionOpacity:

    [xml]$xaml = @"
    <Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="Window" 
           Title="Initial Window" 
           WindowStartupLocation = "CenterScreen" 
           ResizeMode="NoResize"
           SizeToContent = "WidthAndHeight" 
           ShowInTaskbar = "True" 
           Background = "lightgray"> 
        <StackPanel >  
            <Label Content='Type in this textbox' />
            <TextBox x:Name="InputBox" 
                        Height = "50" 
                        SelectionBrush= "Green"
                        SelectionOpacity = "0.5" />  
        </StackPanel>
    </Window>
    "@
    
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
    $Window=[Windows.Markup.XamlReader]::Load( $reader )
    
    
    $Window.ShowDialog() | Out-Null