批处理菜单轮廓和设计

1 windows batch-file

不久前,我在谷歌上搜索以找出如何制作具有更“专业外观”的批处理菜单,而不是使用诸如以下符号:

|=====|
|-----|
|_____|
Run Code Online (Sandbox Code Playgroud)

批量制作菜单周围的轮廓。但我没有运气。今天偶然发现了这篇文章:

https://web.archive.org/web/20151204182221/https://http-server.carleton.ca/~dmcfet/menu.html

它解释了通过使用 ms-dos (edit.com) 我可以做到这一点。但是因为我的电脑是 64 位的 win 10。我有 edit.com 所以....我怎么能手工制作这种菜单?(printing special characters shown on left side of the header "STEP 3, Lines, Lines, Lines.")

roj*_*ojo 7

这是我一直在研究的批处理 + PowerShell 菜单制作工具。在批处理部分设置值,PowerShell 内容将根据需要自动调整大小和重新定位。做出选择后,控制台缓冲区会恢复其先前的内容,从而有效地使菜单消失。

它看起来像这样:

箭头导航菜单

这是代码。使用 .bat 扩展名保存它。

<# : Batch portion
@echo off & setlocal enabledelayedexpansion

set "menu[0]=Format C:"
set "menu[1]=Send spam to boss"
set "menu[2]=Truncate database *"
set "menu[3]=Randomize user password"
set "menu[4]=Download Dilbert"
set "menu[5]=Hack local AD"

set "default=0"

powershell -noprofile "iex (gc \"%~f0\" | out-string)"
echo You chose !menu[%ERRORLEVEL%]!.

goto :EOF
: end batch / begin PowerShell hybrid chimera #>

$menutitle = "=== MENU ==="
$menuprompt = "Use the arrow keys.  Hit Enter to select."

$maxlen = $menuprompt.length + 6
$menu = gci env: | ?{ $_.Name -match "^menu\[\d+\]$" } | %{
    $_.Value.trim()
    $len = $_.Value.trim().Length + 6
    if ($len -gt $maxlen) { $maxlen = $len }
}
[int]$selection = $env:default
$h = $Host.UI.RawUI.WindowSize.Height
$w = $Host.UI.RawUI.WindowSize.Width
$xpos = [math]::floor(($w - ($maxlen + 5)) / 2)
$ypos = [math]::floor(($h - ($menu.Length + 4)) / 3)

$offY = [console]::WindowTop;
$rect = New-Object Management.Automation.Host.Rectangle `
    0,$offY,($w - 1),($offY+$ypos+$menu.length+4)
$buffer = $Host.UI.RawUI.GetBufferContents($rect)

function destroy {
    $coords = New-Object Management.Automation.Host.Coordinates 0,$offY
    $Host.UI.RawUI.SetBufferContents($coords,$buffer)
}

function getKey {
    while (-not ((37..40 + 13 + 48..(47 + $menu.length)) -contains $x)) {
        $x = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode
    }
    $x
}

# http://goo.gl/IAmdR6
function WriteTo-Pos ([string]$str, [int]$x = 0, [int]$y = 0,
    [string]$bgc = [console]::BackgroundColor, [string]$fgc = [Console]::ForegroundColor) {
    if($x -ge 0 -and $y -ge 0 -and $x -le [Console]::WindowWidth -and
        $y -le [Console]::WindowHeight) {
        $saveY = [console]::CursorTop
        $offY = [console]::WindowTop       
        [console]::setcursorposition($x,$offY+$y)
        Write-Host $str -b $bgc -f $fgc -nonewline
        [console]::setcursorposition(0,$saveY)
    }
}

function center([string]$what) {
    $what = "    $what  "
    $lpad = " " * [math]::max([math]::floor(($maxlen - $what.length) / 2), 0)
    $rpad = " " * [math]::max(($maxlen - $what.length - $lpad.length), 0)
    WriteTo-Pos "$lpad   $what   $rpad" $xpos $line blue yellow
}

function menu {
    $line = $ypos
    center $menutitle
    $line++
    center " "
    $line++

    for ($i=0; $item = $menu[$i]; $i++) {
        # write-host $xpad -nonewline
        $rtpad = " " * ($maxlen - $item.length)
        if ($i -eq $selection) {
            WriteTo-Pos "  > $item <$rtpad" $xpos ($line++) yellow blue
        } else {
            WriteTo-Pos " $i`: $item  $rtpad" $xpos ($line++) blue yellow
        }
    }
    center " "
    $line++
    center $menuprompt
    1
}

while (menu) {

    [int]$key = getKey

    switch ($key) {

        37 {}   # left or up
        38 { if ($selection) { $selection-- }; break }

        39 {}   # right or down
        40 { if ($selection -lt ($menu.length - 1)) { $selection++ }; break }

        # number or enter
        default { if ($key -gt 13) {$selection = $key - 48}; destroy; exit($selection) }
    }
}
Run Code Online (Sandbox Code Playgroud)