Search code examples
winformspowershellpowershell-4.0

PowerShell and Windows Forms Tooltip custom colour


I'm trying to customise a simple tooltip with a black background (and black border if possible) and white text. I have the following code, but at the moment it's flakey, sometimes works, other times doesn't.

Can somebody please advise how to make this more reliable? Thanks.

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Windows.Forms.Application]::EnableVisualStyles()

Add-Type -AssemblyName System.Drawing

#create form
$form = New-Object System.Windows.Forms.Form

$shutdownBtn = New-Object System.Windows.Forms.Button
$shutdownBtn.Size = New-Object System.Drawing.Size(200, 40)
$shutdownBtn.Text = "Shut down"

$form.Controls.Add($shutdownBtn)

$tooltip2 = New-Object System.Windows.Forms.ToolTip
$tooltip2.SetToolTip($shutdownBtn, "Shut down.")

$tooltip2.OwnerDraw = $true 
$tooltip2.Add_Draw($tooltip2_Draw)
$tooltip2_Draw=[System.Windows.Forms.DrawToolTipEventHandler]{
        $fontstyle = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Normal)
        $format = [System.Drawing.StringFormat]::GenericTypographic
        $myBrush1 = new-object Drawing.SolidBrush White
        $_.Graphics.DrawString($_.ToolTipText, $fontstyle, $myBrush1, $_.Bounds.X, $_.Bounds.Y, $format)
        $myBrush2 = new-object Drawing.SolidBrush Black
        $_.Graphics.FillRectangle($myBrush2, $_.Bounds)
        $_.DrawBackground()
        $_.DrawBorder()
        $_.DrawText()
 }

$form_cleanup =
{
    $tooltip2.Remove_Draw($tooltip2_Draw)
    $form.remove_FormClosed($form_cleanup)
}

$form.add_FormClosed($form_cleanup)

[void]$form.ShowDialog()
$form.Dispose()

Solution

  • I'll answer my own question:

    There were a couple of glaring errors from a tired mind. Firstly:

    $tooltip2.Add_Draw($tooltip2_Draw) 
    

    should have been called after I declared

    $tooltip2_Draw 
    

    Secondly, I needed to call

    FillRectangle
    

    before i called

    DrawString
    

    And finally, since I set OwnerDraw = $true I didn't need to call:

    $_.DrawBackground()
    $_.DrawBorder()
    $_.DrawText()
    

    So here is the solution:

    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [System.Windows.Forms.Application]::EnableVisualStyles()
    
    Add-Type -AssemblyName System.Drawing
    
    #create form
    $form = New-Object System.Windows.Forms.Form
    
    $shutdownBtn = New-Object System.Windows.Forms.Button
    $shutdownBtn.Size = New-Object System.Drawing.Size(200, 40)
    $shutdownBtn.Text = "Shut down"
    
    $form.Controls.Add($shutdownBtn)
    
    $tooltip2 = New-Object System.Windows.Forms.ToolTip
    $tooltip2.SetToolTip($shutdownBtn, "Shut down now.")
    
    $tooltip2.OwnerDraw = $true 
    $tooltip2_Draw=[System.Windows.Forms.DrawToolTipEventHandler]{
            $fontstyle = new-object System.Drawing.Font('Microsoft Sans Serif', 16, [System.Drawing.FontStyle]::Regular)
            $format = [System.Drawing.StringFormat]::GenericTypographic
            $format.LineAlignment = [System.Drawing.StringAlignment]::Center;
            $format.Alignment = [System.Drawing.StringAlignment]::Center;
            $whiteBrush = new-object Drawing.SolidBrush White
            $blackBrush = new-object Drawing.SolidBrush Black
            $_.Graphics.FillRectangle($blackBrush, $_.Bounds)
            $_.Graphics.DrawString($_.ToolTipText, $fontstyle, $whiteBrush, ($_.Bounds.X + ($_.Bounds.Width/2)), ($_.Bounds.Y + ($_.Bounds.Height/2)), $format)
           
     }
    $tooltip2.Add_Draw($tooltip2_Draw)
    
    $form_cleanup =
    {
        $tooltip2.Remove_Draw($tooltip2_Draw)
        $form.remove_FormClosed($form_cleanup)
    }
    
    $form.add_FormClosed($form_cleanup)
    
    [void]$form.ShowDialog()
    $form.Dispose()