如何解决如何使用Batch在可滚动菜单中进行一系列拨动开关?
我已经花了几个小时这样做。
@echo off
set list = 0 0 1 1
:loop
cls
echo Program Select
echo --------------
set "el=0"
for %%a in (%list%) do (
set /a "el+=1"
if %%a equ 0 echo "[ ] Program %el%"
if %%a equ 1 echo "[X] Program %el%"
)
echo ----------------------------------------------------
echo W = Up / S = Down / L = Toggle / H = Confirm
choice /C WSLH /N >nul
if %ERRORLEVEL% equ 1 set key=UP
if %ERRORLEVEL% equ 2 set key=DN
if %ERRORLEVEL% equ 3 set key=SL
if %ERRORLEVEL% equ 4 set key=CN
echo %key%
pause >nul
goto loop
现在key变量可以正常工作,并且我还没有实现滚动,因为我什至无法获得它来呈现文本。
目标是获得这样的输出
Program Select
--------------
[ ] Program 1
[ ] Program 2
[X] Program 3
[X] Program 4
----------------------------------------------------
W = Up / S = Down / L = Toggle / H = Confirm
但是,我只是获得了程序选择和控件。我想念什么?
解决方法
这是您的代码的更“完善”版本:
@echo off
SETLOCAL enabledelayedexpansion
:: Program names used
set "program[1]=Program one"
set "program[2]=Program two"
set "program[3]=Program three"
set "program[4]=Program four"
set /a maxprogs=4
:: symbols used for statuses
set "symbols= X"
set "symbolsc=-+"
:restart
:: Set original list status. 0=not selected,1=selected;
set "list=0 0 1 1"
set /a cursor=1
:loop
cls
echo Program Select
echo --------------
set /a el=0
for %%a in (%list%) do (
set /a el+=1
if !el!==%cursor% (set "ds=!symbolsc:~%%a,1!") else (set "ds=!symbols:~%%a,1!")
call set "progname=%%program[!el!]%%"
echo [!ds!] !progname!
)
echo ----------------------------------------------------
choice /C WSLHQ /N /M "W = Up / S = Down / L = Toggle / H = Confirm / Q = Quit "
set /a key=%errorlevel%
if %key%==5 goto :eof
if %key%==4 goto confirm
if %key%==3 goto toggle
if %key%==2 if %cursor%==%maxprogs% (set /a cursor=1) else set /a cursor+=1
if %key%==1 if %cursor%==1 (set /a cursor=%maxprogs%) else set /a cursor-=1
goto loop
:confirm
echo Confirmed!
set "runany="
set /a el=0
for %%a in (%list%) do (
set /a el+=1
if %%a==1 (
set /a runany+=1
call set "progname=%%program[!el!]%%"
echo Run !progname!
)
)
if not defined runany echo None selected :(
timeout /t 5 /nobreak
goto restart
:toggle
set "newlist="
set /a el=0
for %%a in (%list%) do (
set /a el+=1
if !el!==%cursor% (
if %%a==0 (set "newlist=!newlist! 1") else (set "newlist=!newlist! 0")
) else set "newlist=!newlist! %%a"
)
set "list=%newlist%"
goto loop
评论:
SETLOCAL enabledelayedexpansion
允许!var!
在循环内访问var
的更改值(%var%
在循环开始前访问原始值执行)。
我使用maxprogs
是为了使列表的扩展很直观-只需跟随弹跳球...
由于光标是静态的,因此我使用symbols
来表示未选择/选定的状态,使用symbolsc
来表示“光标”处于状态时的状态,因此+
是光标在这里被选中,-
在这里被选中
list
的用法与您的版本类似-cursor
用于当前的光标行。
在“显示选择和程序名称”部分,请注意使用!el!
在循环中访问el
的修改值
这里最棘手的是call set "progname=%%program[!el!]%%"
语句。这使用解析技巧来获取程序名称el
的值。例如,假设el
的当前值为2
,则通过将set "progname=%program[2]%"
解释为转义的%%
,在子外壳中执行命令%
。替换el
的 current 值。该子Shell继承了其调用者的环境,因此从计算出的值中分配了目标变量。
我修改了choice
命令以提示输入图例,并添加了Q作为退出的标准。我本来会用UDTRQ来进行上/下/切换/运行/退出,但有一些告诉我您不一定使用英语。
我将errorlevel
设置为key
,以避免必须特别注意保持其值,然后测试了key
仅有的五个感兴趣的值;在其他人身上发出哔哔声(从choice
到现在)。
退出很明显;光标移动只需递增或递减cursor
并检查边界条件以进行滚动。
另外两个例程只是对display-list例程的修改; run
显示程序名称,因为我不知道您要串行还是并行运行程序。
toggle
例程使用相同的技术来重建list
,同时切换第cursor
个元素。
我可以理解设置菜单显示格式的愿望-但是,我不建议您考虑使用该方法。让用户滚动到所需的选项,然后确认它并没有使脚本更易于用户使用。
对于用户而言,只需一次按键就可以从列表中选择一个选项。您可以在选择之后轻松地添加确认,这对于确认操作至关重要。
我已经为菜单(对于Windows 10 )开发了一个模板,如果愿意,可以轻松编写脚本并操作菜单选项。使用模板的实用GUI脚本示例为here
以更简单的方式完成与您想要的输出更加一致的事情:
更新-向后兼容版本:
增强功能:
- 用于菜单选项的数组总共支持36个选择选项
- 颜色模式选择-现在可以在运行时禁用颜色。
- 将旧式操作系统的Findstr颜色输出转换为宏,以加快执行速度。
::: Multi-Use Menu :: Author - T3RRY :: Version 4.2 :: October 2020 ::
::: %Menu% macro - accepts up to 36 options for selection as quoted Args in list form.
::: parameters to call functions with via a given menu can be supplied using Substring modification as exampled.
::: - Multiple selection of menu items achieved using loops.
::: Tests if a menu option is a label and calls if true.
::: Builds a list of selected options [ that can be deselected ] when used in a loop.
@Echo off & Goto :Main
:::::::::::::::::::::::::: [* Balances Environment stack on script completion *]
:End [Endlocal ^& Set "_End=Y" ^& Exit /B 0]
Color 07 & %CLOSE%
:::::::::::::::::::::::::::::::::::::::::::::: Findstr based Colorprint function
::: No longer used within menu macro
::: Unsupported Chars: "<" ">" ":" "\" "/" "?" "&"
:C_out [BG:a-f|0-9][FG:a-f|0-9] ["Quoted Strings" "to print"]
Set "Str_=%*" & Set "_Str=" & For %%G in (!Str_!)Do Set "_Str=!_Str! %%~G"
Set "C_Out=%~1"
Set "_Str=!_Str:%1 =!" & For /F "Delims=" %%G in ("!_Str!")Do Set "_Str=%%~G"
For %%G in (!_Str!) Do Set ".Str=%%G"
If /I "!.Str!" == "Exit" (Set "C_Out=04") Else If /I "!.Str!" == "Next" (Set "C_Out=02") Else If /I "!.Str!" == "Continue" (Set "C_Out=02") Else If /I "!.Str!" == "Back" (Set "C_Out=05") Else If /I "!.Str!" == "Return" (Set "C_Out=05")
<nul set /p ".=%DEL%" > " !_Str!"
findstr /v /a:!C_Out! /R "^$" " !_Str!" nul
del " !_Str!" > nul 2>&1
Echo/
Exit /B 0
::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Key variable and Macro definition
:main
::::::::::::::::::::: [ For readablities sake - %Menu% macro is built from the following ]:
rem ::: Order of definition must be preserved.
rem [* prepare default findstr color for non windows 10 users *]
For /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (set "DEL=%%a")
rem [* default color args for Picked / Not Picked options. Overriden to Echo with Ascii Escape codes if Windows 10 *]
rem [* Color /? for the full combination of colors - BG + FG colors must differ. [BG:a-f|0-9][FG:a-f|0-9] *]
Set "ColText=For %%l in (1 2)Do if %%l==2 (Set "_Str="&(Set "C_Out=!Oline:~0,2!" & Set "_Str=!Oline:~3!")&(For %%s in (!_Str!)Do Set ".Str=%%s")&(If /I "!.Str!" == "Exit" (Set "C_Out=04") Else If /I "!.Str!" == "Next" (Set "C_Out=02") Else If /I "!.Str!" == "Continue" (Set "C_Out=02") Else If /I "!.Str!" == "Back" (Set "C_Out=05") Else If /I "!.Str!" == "Return" (Set "C_Out=05"))&( <nul set /p ".=%DEL%" > " !_Str!" )&( findstr /v /a:!C_Out! /R "^$" " !_Str!" nul )&( del " !_Str!" > nul 2>&1 )& Echo/)Else Set Oline="
Set "_Win10="
Set "_End="
rem [* Test if Windows 10 If true Overide defaults _nP and _P with Echo and VT codes for faster execution with windows 10 *]
wmic OS get OSArchitecture,caption | FIND "10" >nul && ((For /F %%a in ('echo prompt $E ^| cmd')do Set "\E=%%a")&Set "_Win10=_")
If Defined _Win10 (
Set "_nP=Echo/%\E%[90m"& Set "_P=Echo/%\E%[33m"
Echo/Menu Color mode: [L]egacy [W]indows [D]isabled & For /F "Delims=" %%C in (' Choice /N /C:LWD ')Do (
If "%%C" =="L" (
Set "_nP=For %%l in (1 2)Do if %%l==2 (Set "_Str="&(Set "C_Out=!Oline:~0,2!" & Set "_Str=!Oline:~3!")&(For %%s in (!_Str!)Do Set ".Str=%%s")&(If /I "!.Str!" == "Exit" (Set "C_Out=04") Else If /I "!.Str!" == "Next" (Set "C_Out=02") Else If /I "!.Str!" == "Continue" (Set "C_Out=02") Else If /I "!.Str!" == "Back" (Set "C_Out=05") Else If /I "!.Str!" == "Return" (Set "C_Out=05"))&( <nul set /p ".=%DEL%" > " !_Str!" )&( findstr /v /a:!C_Out! /R "^$" " !_Str!" nul )&( del " !_Str!" > nul 2>&1 )& Echo/)Else Set Oline=08"
Set "_P=For %%l in (1 2)Do if %%l==2 (Set "_Str="&(Set "C_Out=!Oline:~0,2!" & Set "_Str=!Oline:~3!")&(For %%s in (!_Str!)Do Set ".Str=%%s")&(If /I "!.Str!" == "Exit" (Set "C_Out=04") Else If /I "!.Str!" == "Next" (Set "C_Out=02") Else If /I "!.Str!" == "Continue" (Set "C_Out=02") Else If /I "!.Str!" == "Back" (Set "C_Out=05") Else If /I "!.Str!" == "Return" (Set "C_Out=05"))&( <nul set /p ".=%DEL%" > " !_Str!" )&( findstr /v /a:!C_Out! /R "^$" " !_Str!" nul )&( del " !_Str!" > nul 2>&1 )& Echo/)Else Set Oline=06"
)
If "%%C" =="D" (Set "_nP=Echo/"& Set "_P=Echo/")
)
) Else (
Set "_nP=For %%l in (1 2)Do if %%l==2 (Set "_Str="&(Set "C_Out=!Oline:~0,2!" & Set "_Str=!Oline:~3!")&(For %%s in (!_Str!)Do Set ".Str=%%s")&(If /I "!.Str!" == "Exit" (Set "C_Out=04") Else If /I "!.Str!" == "Next" (Set "C_Out=02") Else If /I "!.Str!" == "Continue" (Set "C_Out=02") Else If /I "!.Str!" == "Back" (Set "C_Out=05") Else If /I "!.Str!" == "Return" (Set "C_Out=05"))&( <nul set /p ".=%DEL%" > " !_Str!" )&( findstr /v /a:!C_Out! /R "^$" " !_Str!" nul )&( del " !_Str!" > nul 2>&1 )& Echo/)Else Set Oline=08"
Set "_P=For %%l in (1 2)Do if %%l==2 (Set "_Str="&(Set "C_Out=!Oline:~0,2!" & Set "_Str=!Oline:~3!")&(For %%s in (!_Str!)Do Set ".Str=%%s")&(If /I "!.Str!" == "Exit" (Set "C_Out=04") Else If /I "!.Str!" == "Next" (Set "C_Out=02") Else If /I "!.Str!" == "Continue" (Set "C_Out=02") Else If /I "!.Str!" == "Back" (Set "C_Out=05") Else If /I "!.Str!" == "Return" (Set "C_Out=05"))&( <nul set /p ".=%DEL%" > " !_Str!" )&( findstr /v /a:!C_Out! /R "^$" " !_Str!" nul )&( del " !_Str!" > nul 2>&1 )& Echo/)Else Set Oline=06"
Echo/Menu Color mode: [L]egacy [D]isabled & For /F "Delims=" %%C in (' Choice /N /C:LD ')Do If "%%C" =="D" (Set "_nP=Echo/"& Set "_P=Echo/")
)
)
rem [* Menu supports 36 choices using _O array index with substring modification on _Cho var to index choice selection of Array Elements *]
Set "_Cho=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set "DisplayArray=(Echo/!#Sel!| Findstr /LIC:"%%~G" > Nul 2> Nul && ( %_P% [!_Cho:~%%z,1!] X %%~G ) ) || ( %_nP% [!_Cho:~%%z,1!] - %%~G )"
Set "#Sel=_Nil"
Set "ClearArray=(For /F "Tokens=1,2 Delims==" %%i in (' Set Opt[ 2^> Nul ')Do "Set %%i=")"
Set "ResetVars=(Set "#L=F" & Set "OptL=" & Set "_O=0")"
Set "CLOSE=POPD & Endlocal & Set "_End=Y" & Exit /B 0"
Set "BuildArray=((If !_O! GTR 35 (Call :C_Out 04 "Maximum options [!_O!] Exceeded" & (Timeout /T 5 /NOBREAK) & %CLOSE%))&Set "OptL=!OptL!!_Cho:~%%z,1!"&Set "Opt[!_Cho:~%%z,1!]=%%~G")"
Set "MakeChoice=(For /F "Delims=" %%C in ('Choice /N /C:!OptL!')Do findstr.exe /BLIC:":!Opt[%%C]!" "%~F0" > nul 2> nul && Call :!Opt[%%C]! "Param" 2> Nul || ((Echo/"!#Sel!"| Findstr /LIC:"!Opt[%%C]!" > Nul 2> Nul && (For /F "Delims=" %%r in ("!Opt[%%C]!")Do If Not "!#Sel!" == "" (Set "#Sel=!#Sel:"%%r"=!")Else (Set "#Sel=_Nil"))) || (Set "#Sel=!#Sel! "!Opt[%%C]!"")))"
Set "Return=For /L %%s in (0 1 4)Do (If not "!#Sel!" == "" (If "!#Sel:~0,1!" == " " (If "!#L!" == "F" (Set "#Sel=!#Sel:~1!"))Else (Set "#L=T"))Else (Set "#Sel=_Nil"))&if not "!#Sel!" == "_Nil" if not "!#Sel!" == "" (Set "#Sel=!#Sel:_Nil=!")"
Set "Menu=(If defined _End Goto :End) &For %%n in (1 2)Do if %%n==2 (%ClearArray% & %ResetVars% &(For %%G in (!Options!)Do For %%z in (!_O!)Do %BuildArray% & %DisplayArray% &Set /A "_O+=1")& %MakeChoice% & %Return% )Else Set Options="
For %%M in ( ClearArray ResetVars BuildArray DisplayArray MakeChoice Return )Do Set "%%M="
IF NOT EXIST "%TEMP%\colorize" md "%TEMP%\colorize"
PUSHD "%TEMP%\colorize" || (Echo/"%TEMP%\colorize" Could not be found & %CLOSE%)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Setlocal EnableExtensions EnableDelayedExpansion & REM [* required to be activated AFTER definition of Macro's. *]
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Commence script main body | Demonstration of usages
:Loop
rem [* doublequoting of options recommended - Required for strings containing standard delimiters. *]
If not defined _End cls
If not defined _End %ColText%05 Make a selection.
rem [* Param Substring modification examples passing parameters to labels called when selected - Optional feature. *]
Set /A "PRM=!Random! %%100 + 100" & Rem [* Example param only *]
%Menu:Param=PRM% "Exit" "Next" "Option 1" "Option 2" "Option 3" "Option 4"
Echo/"!#Sel!" | Findstr.exe /LIC:"Exit" > Nul 2> Nul && (Goto :End)
Goto :Loop
:Next
rem [* Selection of a single option occurs by using the macro without a loop or resetting the #Sel variable
rem - between %menu% use and next iteration of a loop *]
rem [* Process #Sel items using the !#Sel! variable - then ** SET "#Sel-_Nil" prior to next usage of Menu macro** *]
Set "Menu1Opts=!#Sel!"
Set "#Sel="
Cls
Call :C_Out 03 "[Demo - Parameter usage. %%1 ~ '%1' == '!%~1!' ] Selected =" !Menu1opts!
%Menu% "Exit" " + Continue" ".. Back"
Echo/!#Sel! | Findstr.exe /LIC:".. Back" > Nul 2> Nul && (Set "#Sel=!Menu1opts!"& Exit /B 0)
Echo/!#Sel! | Findstr.exe /LIC:"Exit" > Nul 2> Nul && (%CLOSE%)
Set "#Sel="
Echo/!Menu1opts! | Findstr.exe /LIC:"_Nil" > Nul 2> Nul && (Call :C_Out 04 "Selection Required."&(Pause & Exit /B 0)) || Call :C_Out 02 "Confirmed=" !Menu1opts!
Call :C_Out 02 "Example complete."
Pause
rem [* to exit at end of script or by user selection *]
%CLOSE%
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: End of example
输出:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。