how do i make a box menu? how do i highlight the selection?

You can add color in (I used Green, but that’s up to you) with some minor adjustments to your code:

function Create-Menu {
    Param(
        [Parameter(Mandatory=$True)][String]$MenuTitle,
        [Parameter(Mandatory=$True)][array]$MenuOptions
    )

    # test if we're not running in the ISE
    if ($Host.Name -match 'ISE') {
        Throw "This menu must be run in PowerShell Console"
    }

    $MaxValue = $MenuOptions.Count-1
    $Selection = 0
    $EnterPressed = $False

    While(!$EnterPressed) {
        # draw the menu
        Clear-Host
        for ($i = 0; $i -le $MaxValue; $i++){
            [int]$Width = [math]::Max($MenuTitle.Length, ($MenuOptions | Measure-Object -Property Length -Maximum).Maximum)
            [int]$Buffer = if (($Width * 1.5) -gt 78) { (78 - $width) / 2 } else { $width / 4 }
            $Buffer = [math]::Min(6, $Buffer)
            $MaxWidth = $Buffer * 2 + $Width + $MenuOptions.Count.ToString().Length
            Write-Host ("╔" + "═" * $maxwidth + "╗")
            # write the title if present
            if (!([string]::IsNullOrWhiteSpace($MenuTitle))) {
                $leftSpace  = ' ' * [Math]::Floor(($maxwidth - $MenuTitle.Length)/2)
                $rightSpace = ' ' * [Math]::Ceiling(($maxwidth - $MenuTitle.Length)/2)
                Write-Host ("║" + $leftSpace + $MenuTitle + $rightSpace + "║")
                Write-Host ("╟" + "─" * $maxwidth + "╢")
            }
            # write the menu option lines
            for($i = 0; $i -lt $MenuOptions.Count; $i++){
                $Item = "$($i + 1). "
                $Option = $MenuOptions[$i]
                $leftSpace  = ' ' * $Buffer
                $rightSpace = ' ' * ($MaxWidth - $Buffer - $Item.Length - $Option.Length)
                $line = "║" + $leftSpace + $Item + $Option + $rightSpace + "║"
                if ($Selection -eq $i) {
                    Write-Host $line -ForegroundColor Green
                }
                else {
                    Write-Host $line
                }
            }
            Write-Host ("╚" + "═" * $maxwidth + "╝")
        }
        # wait for an accepted key press
        do {
            $KeyInput = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode
        } while (13, 38, 40 -notcontains $KeyInput)


        Switch($KeyInput){
            13{
                $EnterPressed = $True
                return $Selection
            }
            38 {
                $Selection--
                if ($Selection -lt 0){ $Selection = $MaxValue }
                break
            }
            40 { 
                $Selection++
                if ($Selection -gt $MaxValue) { $Selection = 0 }
                # or:    $Selection = ($Selection + 1) % ($MaxValue + 1)
                break
            }
        }
    }
}

#MainMenu
function MainMenu {
    $selected = Create-Menu -MenuTitle "Tools" -MenuOptions "Lookup","Prep","Tools","Settings","Cleanup and Exit"
    switch ($selected) {
        0 {"Lookup"}
        1 {"PrepMenu"}
        2 {"ToolsMenu"}
        3 {"SettingsMenu"}
        4 {"CleanupAndExit"}
    }
}

MainMenu

Edit

Just for the fun of it, the above code uses Clear-Host before each redraw of the menu which results in a workable, but flickering menu.
Below the same menu, but this time it redraws without first clearing the console window resulting in a much smoother menu.

function Create-Menu {
    Param(
        [Parameter(Mandatory=$false)][string]  $MenuTitle = $null,
        [Parameter(Mandatory=$true)] [string[]]$MenuOptions
    )

    # test if we're not running in the ISE
    if ($Host.Name -match 'ISE') {
        Throw "This menu must be run in PowerShell Console"
    }

    $MaxValue = $MenuOptions.Count-1
    $Selection = 0
    $EnterPressed = $False
    [console]::CursorVisible = $false  # prevents cursor flickering
    Clear-Host

    while(!$EnterPressed) {
        # draw the menu without Clear-Host to prevent flicker
        [console]::SetCursorPosition(0,0)
        for ($i = 0; $i -le $MaxValue; $i++){
            [int]$Width = [math]::Max($MenuTitle.Length, ($MenuOptions | Measure-Object -Property Length -Maximum).Maximum)
            [int]$Buffer = if (($Width * 1.5) -gt 78) { (78 - $width) / 2 } else { $width / 4 }
            $Buffer = [math]::Min(6, $Buffer)
            $MaxWidth = $Buffer * 2 + $Width + $MenuOptions.Count.ToString().Length
            Write-Host ("╔" + "═" * $maxwidth + "╗")
            # write the title if present
            if (!([string]::IsNullOrWhiteSpace($MenuTitle))) {
                $leftSpace  = ' ' * [Math]::Floor(($maxwidth - $MenuTitle.Length)/2)
                $rightSpace = ' ' * [Math]::Ceiling(($maxwidth - $MenuTitle.Length)/2)
                Write-Host ("║" + $leftSpace + $MenuTitle + $rightSpace + "║")
                Write-Host ("╟" + "─" * $maxwidth + "╢")
            }
            # write the menu option lines
            for($i = 0; $i -lt $MenuOptions.Count; $i++){
                $Item = "$($i + 1). "
                $Option = $MenuOptions[$i]
                $leftSpace  = ' ' * $Buffer
                $rightSpace = ' ' * ($MaxWidth - $Buffer - $Item.Length - $Option.Length)
                $line = "║" + $leftSpace + $Item + $Option + $rightSpace + "║"
                if ($Selection -eq $i) {
                    Write-Host $line -ForegroundColor Green
                }
                else {
                    Write-Host $line
                }
            }
            Write-Host ("╚" + "═" * $maxwidth + "╝")
        }
        # wait for an accepted key press
        do {
            $KeyInput = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode
        } while (13, 38, 40 -notcontains $KeyInput)


        Switch($KeyInput){
            13{
                $EnterPressed = $True
                [console]::CursorVisible = $true  # reset the cursors visibility
                return $Selection
            }
            38 {
                $Selection--
                if ($Selection -lt 0){ $Selection = $MaxValue }
                break
            }
            40 { 
                $Selection++
                if ($Selection -gt $MaxValue) { $Selection = 0 }
                # or:    $Selection = ($Selection + 1) % ($MaxValue + 1)
                break
            }
        }
    }
}

#MainMenu
function MainMenu {
    $selected = Create-Menu -MenuTitle "Tools" -MenuOptions "Lookup","Prep","Tools","Settings","Cleanup and Exit"
    switch ($selected) {
        0 {"Lookup"}
        1 {"PrepMenu"}
        2 {"ToolsMenu"}
        3 {"SettingsMenu"}
        4 {"CleanupAndExit"}
    }
}

MainMenu

enter image description here

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top