Advanced Batch features via auxiliary .exe programs

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Advanced Batch features via auxiliary .exe programs

#1 Post by Aacini » 15 Jun 2012 20:44

Batch file capabilities can be improved via external .exe files, in the same way provided by the standard DOS-Windows external commands (findstr.exe, sort.exe, etc). I developed a series of auxiliary commands that provide some additional features to Batch programs, so we can use these commands to assemble a more complex advanced facilities. These auxiliary programs are native Windows console applications, so they run in any Windows version. To keep the programs small, they do not show any error message nor help description; if a parameter is wrong, the program just terminate at that point; the full description is given below. To get a copy of these commands, copy the desired CommandName.exe.hex file and convert it via HexToBin.bat conversion program.

EDIT: A new simpler method to get these programs is available. Just download the next "Auxiliary .exe programs.zip" attached file and extract all auxiliary .exe programs and their descriptions from it.
EDIT - 2016/12/04: Includes updated version of GetInput.exe and new SendMessage.exe program.
EDIT - 2016/12/21: Includes GetInput.exe version 1.2 with "mouse hovering support".

This is a list of the programs included in this file grouped by type of operation. Each .exe program have a .txt companion file that contains the program description. In certain .txt files there is a link to particular examples of such a program; you may review and post questions about these programs at the given links.

Code: Select all

String manipulation:
====================

StrLen.exe              Get the length of string literals and Batch variables.
Ascii.exe               Show Ascii codes of string literals and Batch variables.

Keyboard input:
===============

GetKey.exe              Get a key from keyboard and return its value.
ShowKeyCodes.bat        Display the codes returned by GetKey for all keys.
FlushInputBuffer.exe    Clear the input buffer from any previous keystroke.
GetInput.exe            Read input from both keyboard keys and mouse clicks.

Screen output:
==============

CursorPos.exe           Get or set cursor position.
CursorSize.exe          Get or set cursor size.
Show.exe                Show characters from Ascii codes, literals and variables.
ColorShow.exe           Show characters in the same way as Show.exe, but in color.
ColorChar.exe           Stripped down version of ColorShow.exe with no variables.
ColorBox.exe            Show a box in text mode using line-drawing characters.
DefineColorCodes.bat    Define values useful to write color attributes.
Window.exe              Get/set several values related to console screen window.

Date and Time:
==============

StdTime.exe             Get a standard time and convert it to milliseconds.
ElapsedTime.bat         Display elapsed times in a standard format.
StdDate.exe             Get a standard date and convert it to Julian Day Number.
EasterSunday.bat        Calculate the date of Christian Easter Sunday.

File handle management:
=======================

GetFileType.exe         Get the type of the file connected to a file handle.
FilePointer.exe         Move the file pointer of the redirected disk file.
TruncateFile.exe        Truncate the size of the redirected disk file.
ReadFile.exe            Read bytes from a redirected input file handle.

Miscellaneous programs:
=======================

printf.exe              Show formatted output and evaluate RPN arithmetic expressions.
SendMessage.exe         Send a System-Defined Message to a window.
Auxiliary .exe programs.zip
(36.06 KiB) Downloaded 7954 times

EDIT: Below there is an index of these auxiliary commands and example programs with the number of the particular reply, if any, where each program was posted. Just copy the &p=... part and paste it in the address bar after t=3428.
INDEX wrote: String manipulation.
    StrLen.exe
        Get the length of string literals and Batch variables.
    Ascii.exe &p=17750#p17750
        Show Ascii codes of string literals and Batch variables.

Keyboard input.
    GetKey.exe
        Get a key from keyboard and return its value in ERRORLEVEL.
    SHOWKEYCODES.BAT
        Display the codes returned by GetKey for all special keys in the keyboard.
    :ReadLine.bat
        Read a line from keyboard emulating SET /P command.
    FlushInputBuffer.exe
        Clear the input buffer of any previous keystroke.

Screen management.
    CursorPos.exe.hex &p=17216#p17216
        Get or set cursor position.
    :GetCoords.bat &p=17216#p17216
        Separate the coordinates value given by CursorPos in Column & Row.
    Show.exe
        Show characters from Ascii codes, string literals and Batch variables.
    CursorSize.exe &p=17750#p17750
        Get or set cursor size.
    TEXTANIMATION.BAT &p=17912#p17912
        Basic example of text animation.
    SNAKE.BAT &p=17216#p17216
        Basic example of an interactive animation video game program.
    Window.exe &p=17216#p17216
        Get or set some values related to console screen window.

Display colors in the screen.
    :DefineColorCodes.bat &p=17750#p17750
        Define auxiliary variables for color attributes.
    TextColor.exe &p=17750#p17750
        Get or set text color.
    ColorShow.exe &p=17750#p17750
        Show characters in color.
    :Select.bat &p=17750#p17750
        Activate a selection of options in one line.

Date and Time management.
    StdTime.exe &p=17610#p17610
        Get standard time fields and convert they to/from number of milliseconds.
    :ElapsedTime.bat &p=17610#p17610
        Display elapsed times in a readable format.
    StdDate.exe &p=17610#p17610
        Get standard date fields and convert they to/from Julian Day Number.
    :EasterSunday &p=17610#p17610
        Calculate the date of Christian Easter Sunday of any given year.

File management.
    FileSize.exe Soon
        Get file size in maximum columns and number of lines.
    HandleType.exe Soon, preliminary version in: t=2800 (change t=3428 part)
        Identify a redirected standard handle.
    FilePointer.exe Soon, preliminary version in: t=2823 (change t=3428 part)
        Get or set file pointer of redirected standard handles.
1- StrLen.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]D5FA31DE919B5F8D919B5F8D919B5F8D1F844C8D979B5F8D6D
BB4D8D939B5F8D52696368919B5F8D[8]5045[2]4C010200C0D6D34F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1020[2]28[84]20[2]10[27]2E74657874[3]C0[4]10[3]02[3]02[14]20[2]602E
7264617461[2]90[4]20[3]02[3]04[14]40[2]40[8]E806[3]50E8A3[3]558BEC83C4F8C745F8[4]E863[3]E882[3]8A064684C0744C3C22
75198A064684C074413C227405FF45F8EBF08A06463C2274F4EBD78BFE4F8A1E80FB20740784DB740346EBF2C606006A018D
45FF5057E84E[3]0145F883F8017E03FF4DF8881EEBA88B45F8C9C3CCCCCCCCCCCCE835[3]8BF08A06463C2275098A06463C22
75F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2508204000FF2500204000FF25042040[321]5620[2]7020
[2]4820[6]3820[10]8220[3]20[22]5620[2]7020[2]4820[6]9B004578697450726F63657373001301476574456E7669726F6E6D656E
745661726961626C654100E600476574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[370]
StrLen.exe description wrote: Get the length of string literals and Batch variables.

StrLen "literal" | variable ...

At end, the accumulated length of all strings is returned in ERRORLEVEL.
EDIT: I slightly modified Show.exe program to also accept an X-letter instead an asterisk in CODExTIMES parameter.

2- Show.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]5527D9C81146B79B1146B79B1146B79B9F59A49B1946B79BED
66A59B1346B79B526963681146B79B[8]5045[2]4C010200935FFF4F[8]E0000F010B01050C0004[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1820[2]28[84]20[2]18[27]2E74657874[3]0C03[3]10[3]04[3]02[14]20[2]60
2E7264617461[2]BC[4]20[3]02[3]06[14]40[2]40[8]E806[3]50E8E302[2]558BEC81C4E8DFFFFFFCC785E8DFFFFF[4]6AF5E8D402[2]89
45FC8DBDFCDFFFFF89BDF8DFFFFFE88602[2]E8A502[2]8A064684C00F842A02[2]3C22751D8A064684C00F841B02[2]3C227405
880747EBEC8A06463C2274F4EBCF3C3072443C397740E82A02[2]3C2A74083C5874043C78752A8ADC468A06463C300F82E201
[2]3C390F87DA01[2]E80302[2]0FB6CC8885F7DFFFFF8AC3F3AAEB8C882747EB872BBDF8DFFFFF741E01BDE8DFFFFF6A008D85
ECDFFFFF5057FFB5F8DFFFFFFF75FCE82702[2]8BFE4F33DB889DF6DFFFFF8A063C3A74118885F7DFFFFF3C20746084C0745C
46EBE9889DF6DFFFFFC60600468A06463C2D7509C685F6DFFFFF02EB0B3C2B750AC685F6DFFFFF018A06463C300F826F01[2]3C
390F876701[2]E86A01[2]8885F7DFFFFF3C20740884C00F855001[2]84E40F840901[2]8ADCC60600680020[2]8D85FCDFFFFF50
57E88B01[2]85C00F84EA[3]85DB0F84A0[3]3BC37C2C80BDF6DFFFFF00741DF685F6DFFFFF01750A2BC30185F8DFFFFFEB0A2B
C3D1E80185F8DFFFFF8BC333DBEB702BD88BBDF8DFFFFF03F889BDF0DFFFFF50B0208BCBF3AA80BDF6DFFFFF00744FF685F6
DFFFFF027422019DE8DFFFFF6A008D85ECDFFFFF5053FFB5F0DFFFFFFF75FCE81001[2]33DBEB248BFBD1EF2BDF01BDE8DFFF
FF6A008D85ECDFFFFF5057FFB5F0DFFFFFFF75FCE8E8[3]588BF801BDE8DFFFFF6A008D85ECDFFFFF5057FFB5F8DFFFFFFF75
FCE8C7[3]85DB741E019DE8DFFFFF6A008D85ECDFFFFF5053FFB5F0DFFFFFFF75FCE8A5[3]8A85F7DFFFFF88068DBDFCDFFFFF
89BDF8DFFFFFE9C6FDFFFF2BBDF8DFFFFF741E01BDE8DFFFFF6A008D85ECDFFFFF5057FFB5F8DFFFFFFF75FCE866[3]8B85E8
DFFFFFC9C3240F8AE08A06463C30720C3C3977082C30D50A8AE0EBED4EC3CCCCCCCCCCE841[3]8BF08A06463C2275098A0646
3C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2510204000FF2500204000FF2504204000FF2508
204000FF250C2040[245]6620[2]8020[2]9020[2]9C20[2]5820[6]4020[10]AE20[3]20[22]6620[2]8020[2]9020[2]9C20[2]5820[6]9B0045
78697450726F63657373001301476574456E7669726F6E6D656E745661726961626C6541006A0147657453746448616E646C
65[2]F702577269746546696C6500E600476574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[326]
Show.exe description wrote: Show characters from Ascii codes, string literals and Batch variables.

Show code[*times] | "literal" | variable[:[±]wide] ...

<code>, <times> and <wide> must be decimal numbers up to 255 each.

Times repeat the previous Ascii code character that number of times.
Wide define a width to show the variable value: justified at left, or justified at rigth if <wide> have minus sign, or centered if <wide> have plus sign.

At end, the number of displayed characters is returned in ERRORLEVEL.
Example:

Code: Select all

@echo off
setlocal EnableDelayedExpansion
set Num1=1
set Num2=2
Show "Result one: " Num1 9 9 "Result two: " Num2 13 10 "Next line" 13 10
set LF=^


for /F "tokens=1-4 delims= " %%a in ('Show 7 32 8 32 9 32 13 32') do (
   set "BEL=%%a" & set "BS=%%b" & set "TAB=%%c" & set "CR=%%d"
)
echo BEL: %BEL%
echo BS:  One%BS%Two
echo TAB: One%TAB%Two
echo LF:  One!LF!Two
echo CR:  One!CR!Two
Show "Result one: " Num1 TAB TAB "Result two: " Num2 CR LF "Next line" CR LF
Output:

Code: Select all

Result one: 1           Result two: 2
Next line
BEL:
BS:  OnTwo
TAB: One        Two
LF:  One
Two
Two  One
Result one: 1           Result two: 2
Next line
If an Ascii code is followed by an asterisk and counter, the character is repeated that number of times. For example, the Batch subroutine below show a frame in the screen given the width and height:

Code: Select all

:ShowFrame width height
set /A width=%1-2, height=%2-2
Show 218 196*%width% 191  13 10
for /L %%i in (1,1,%height%) do Show 179 32*%width% 179  13 10
Show 192 196*%width% 217  13 10
exit /B
If a variable is followed by a colon and wide, it is adjusted to fit/fill that number of characters. The adjustment is usually done at right side of variable value, but if wide have minus sign the adjustment will be done at left side, and if wide have plus sign the adjustment will be done at both sides of variable value (centered). For example, the Batch subroutine below show the contents of a (small) text file centered into a single-line frame:

Code: Select all

:ShowFileInFrame filename
rem Load file lines and get max line length
set i=0
set maxLen=0
for /F "delims=" %%a in (%1) do (
   set /A i+=1
   set "line[!i!]=%%a"
   StrLen line[!i!]
   if !errorlevel! gtr !maxLen! set maxLen=!errorlevel!
)
rem Show file lines into a frame
Show 218 196*%maxLen% 191  13 10
for /L %%i in (1,1,%i%) do Show 179 line[%%i]:+%maxLen% 179  13 10
Show 192 196*%maxLen% 217  13 10
For example, if we use this data file:
Datafile.txt wrote: This is a small example file
comprised of four lines of text
with a longest line
of thirty one characters
... previous subroutine produce this output:

Code: Select all

┌───────────────────────────────┐
│ This is a small example file  │
│comprised of four lines of text│
│      with a longest line      │
│   of thirty one characters    │
└───────────────────────────────┘
These subroutines use Ascii "line" characters of standard code pages 850 and 437. If "line" characters not appear in your screen, insert a CHCP 850 command at beginning.


3- GetKey.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]55B5B8FD11D4D6AE11D4D6AE11D4D6AE9FCBC5AE18D4D6AEED
F4C4AE13D4D6AE5269636811D4D6AE[8]5045[2]4C0102005A66D14F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1820[2]3C[84]20[2]18[27]2E74657874[3]96[4]10[3]02[3]02[14]20[2]602E
7264617461[2]BA[4]20[3]02[3]04[14]40[2]40[8]E806[3]50E873[3]E840[3]E85F[3]803E00741866813E2F57740766813E2F77740A
FF150C20400085C07419FF151020400085C074073DE0[3]7508FF1510204000F7D8C3CCCCCCCCE82F[3]8BF08A06463C227509
8A06463C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2504204000FF2500204000FF2510204000FF
250C2040[363]7A20[2]6C20[6]A420[2]9A20[6]5420[10]8C20[3]20[2]6020[10]AE20[2]0C20[22]7A20[2]6C20[6]A420[2]9A20[6]9B004578
697450726F6365737300E600476574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[2]CE005F6765746368[2]11
015F6B62686974[2]6D73766372742E646C6C[328]
GetKey.exe description wrote: Get a key from keyboard and return its value in ERRORLEVEL.

GetKey [/N]

Ascii characters are returned as positive values, extended keys as negative values.

If /N switch is given, no wait for a key: immediately return zero if no key was pressed.
The program below (SHOWKEYCODES.BAT) display the codes returned by GetKey for all special keys in the keyboard, including Shift-, Ctrl- and Alt- combinations. You may run this program and copy just the specific codes you need.

Code: Select all

@echo off
setlocal EnableDelayedExpansion
(for /F "delims==" %%a in ('set') do (
   echo %%a
)) > vars.txt
call :DefineKeyCodes
set a=a
< vars.txt (
for /F "tokens=1* delims==" %%a in ('set') do (
   if "!a!" equ "%%a" (
      set /P a=
   ) else (
      echo %%a=%%b
   )
))
del vars.txt
goto :EOF


:DefineKeyCodes
rem Definition of key codes via key names
rem Antonio Perez Ayala

rem Require Delayed Expansion. Modify "i" variable.
rem Can not use Setlocal because its purpose is to create global variables

for %%a in ("BackSpace=8" "TabKey=9" "Ctrl_Enter=10" "EnterKey=13" "EscKey=27" "Ctrl_@=-3") do (
   set %%a
)
set i=-14
for %%a in (Alt_BackSpace Shift_Tab) do (
   set %%a=!i!
   set /A i-=1
)
rem Currently: i=-16
for %%a in (Q W E R T Y U I O P LeftBracket RightBracket) do (
   set Alt_%%a=!i!
   set /A i-=1
)
set i=-30
for %%a in (A S D F G H J K L Semicolon Apostrophe BackQuote) do (
   set Alt_%%a=!i!
   set /A i-=1
)
set i=-43
for %%a in (BackSlash Z X C V B N M Comma Dot Slash "" GrayStar) do (
   set Alt_%%~a=!i!
   set /A i-=1
)
set i=-59
for %%a in (F1 F2 F3 F4 F5 F6 F7 F8 F9 F10) do (
   set %%a=!i!
   set /A i-=1
)
set i=-71
for %%a in (HomeKey UpArrow PageUp Alt_GrayDash LeftArrow KeyPad5 RightArrow
            Alt_GrayPlus EndKey DownArrow PageDown InsKey DelKey) do (
   set %%a=!i!
   set /A i-=1
)
rem Currently: i=-84
for %%a in (Shift Ctrl Alt) do (
   for %%b in (F1 F2 F3 F4 F5 F6 F7 F8 F9 F10) DO (
      set %%a_%%b=!i!
      set /A i-=1
   )
)
rem Currently: i=-114
for %%a in (PrtSc LeftArrow RightArrow End PageDown Home) do (
   set Ctrl_%%a=!i!
   set /A i-=1
)
rem Currently: i=-120
for %%a in (1 2 3 4 5 6 7 8 9 0 Dash Equal) do (
   set Alt_%%a=!i!
   set /A i-=1
)
rem Currently: i=-132
for %%a in (Ctrl_PageUp F11 F12 Shift_F11 Shift_F12 Ctrl_F11 Ctrl_F12 Alt_F11 Alt_F12) do (
   set %%a=!i!
   set /A i-=1
)
rem Currently: i=-141
for %%a in (UpArrow GrayDash KeyPad5 GrayPlus DownArrow Ins Del Tab GraySlash GrayStar) do (
   set Ctrl_%%a=!i!
   set /A i-=1
)
rem Currently: i=-151
for %%a in (Home UpArrow PageUp "" LeftArrow KeyPad5 RightArrow "" End
            DownArrow PageDown Ins Del GraySlash) do (
   set Alt_%%~a=!i!
   set /A i-=1
)
set Alt_=
set i=

exit /B
ReadLine subroutine below process keystrokes one-by-one to read a line emulating SET /P command (BackSpace delete last character, Enter terminate the line). In this case, the "prompt" must be enclosed in quotes and the variable will be erased if the input line is empty:

Code: Select all

@echo off
set Bell=7
set BackSpace=8
set Enter=13
set Space=32

:ReadLine var=["prompt"]
set %1=
if "%~2" neq "" Show %2
:nextKey
   GetKey
   set key=%errorlevel%
   if %key% geq %Space% (
      rem Ascii character
      Show %key%
      for /F "delims=" %%a in ('Show %key%') do set "%1=!%1!%%a"
   ) else if %key% equ %BackSpace% (
      if defined %1 (
         Show %BackSpace% %Space% %BackSpace%
         set "%1=!%1:~0,-1!"
      ) else (
         Show %Bell%
      )
   ) else if %key% equ %Enter% echo/& exit /B
goto nextKey
Previous routine may be easily modified to suit specific needs. For example, to read digits only:

Code: Select all

set Digit_0=48
set Digit_9=57

   . . .
   rem Ascii character: ignore characters that are not digits
   if %key% lss %Digit_0% goto nextKey
   if %key% gtr %Digit_9% goto nextKey
   Show %key%
   . . .
To convert lower-case letters to upper-case ones:

Code: Select all

set and=if
set Upcase_A=65
set Lowcase_a=97
set Lowcase_z=122

   . . .
   rem Ascii character: convert lowcase letters to upcase ones
   if %key% geq %Lowcase_a% %and% %key% leq %Lowcase_z% set /A key-=Lowcase_a-Upcase_A
   Show !key!
   . . .
To read a password, just echo an asterisk instead of the same key read:

Code: Select all

   . . .
   rem Ascii character: get it, but echo an asterisk
   Show "*"
   . . .
You may also codify the password character read so the real password never appear in the source Batch program.

/N switch is useful to control actively interactive programs; for example, a program may repeat a loop until a key is pressed:

Code: Select all

:loop
   rem Do a repetitive process here
   GetKey /N
if %errorlevel% equ 0 goto loop
Of course, more complex interactive routines are also possible. For example, the subroutine below perform a timed read line, that is, it limits the time allowed to complete the input to a given number of seconds; if that time is exceeded, "Input timeout" is assigned to the input variable:

Code: Select all

@echo off
set Bell=7
set BackSpace=8
set Enter=13
set Space=32

:ReadLineTime var= seconds ["prompt"]
set %1=
set seconds=%2
Show %3 seconds ": "
set lastTime=%time:~0,-3%
:nextKey
   GetKey /N
   set key=%errorlevel%
   if %key% equ 0 (
      if %lastTime% equ %time:~0,-3% (
         goto nextKey
      ) else (
         set lastTime=%time:~0,-3%
         set /A seconds-=1
         if !seconds! gtr 0 (
            Show 13 %3 seconds ": " %1 " " %BackSpace%
            goto nextKey
         ) else (
            StrLen %1
            Show 13 %3 "0: " %Space%*!errorlevel! 13 10
            set %1=Input timeout
            exit /B 1
         )
      )
   )
   if %key% geq %Space% (
      rem Ascii Character
      Show %key%
      for /F "delims=" %%a in ('Show %key%') do set "%1=!%1!%%a"
   ) else if %key% equ %BackSpace% (
      if defined %1 (
         Show %BackSpace% %Space% %BackSpace%
         set "%1=!%1:~0,-1!"
      ) else (
         Show %Bell%
      )
   ) else if %key% equ %Enter% echo/& exit /B
goto nextKey
When GetKey /N command is used, cancelling any previous keystroke is sometimes required. This can be done with the following program.


4- FlushInputBuffer.exe.hex

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]551E49C1117F2792117F2792117F27929F603492167F2792ED
5F3592137F279252696368117F2792[8]5045[2]4C010200D319C84F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1420[2]28[84]20[2]14[27]2E74657874[3]66[4]10[3]02[3]02[14]20[2]602E
7264617461[2]A8[4]20[3]02[3]04[14]40[2]40[8]6AF6E853[3]50E847[3]6A00E83A[3]CCCCCCCCCCCCCCCCCCCCCCCCE83B[3]8BF08A
06463C2275098A06463C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF250C204000FF2500204000FF
2504204000FF25082040[411]5E20[2]7820[2]8820[2]5020[6]3C20[10]9A20[3]20[22]5E20[2]7820[2]8820[2]5020[6]9B004578697450
726F6365737300C600466C757368436F6E736F6C65496E707574427566666572006A0147657453746448616E646C65[2]E60047
6574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[346]
FlushInputBuffer.exe description wrote: Clear the input buffer of any previous keystroke.

FlushInputBuffer

Feel free to copy and use these programs in any way you wish. I'd appreciate it if you report any problem you may find. If you use anyone of these programs to write and publish a Batch-file application, then you should not copy these *.exe files directly in your distribution; instead, you should include a link to this site so final users can copy the last version of the auxiliary program besides the help .txt file and examples.

Antonio
Last edited by Aacini on 26 Jul 2016 13:52, edited 5 times in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#2 Post by Ed Dyreen » 16 Jun 2012 00:29

'
Abra cadabra :P I like the getkey :D

Thanks Aacini,

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#3 Post by Aacini » 20 Jun 2012 21:14

The following Batch subroutine separate in two 16-bits numbers the 32-bits ERRORLEVEL value returned by some auxiliary programs:

Code: Select all

:GetCoords Cols= Lines=
set /A "%1=%errorlevel%&0xFFFF, %2=(%errorlevel%>>16)&0xFFFF"
exit /B



EDIT: I added optional parameters to Window GSize command. The following .hex file contain the updated version and the new parameters are described below.

5- Window.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B8[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]19D9A1555DB8CF065DB8CF065DB8CF06D3A7DC064FB8CF06A1
98DD065FB8CF06526963685DB8CF06[16]5045[2]4C010300E785E74F[8]E0000F010B01050C0004[3]04[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]40[3]04[6]03[5]10[2]10[4]10[2]10[6]10[11]3C20[2]3C[84]20[2]3C[27]2E74657874[3]2C03[3]10[3]04[3]04[14]20[2]60
2E7264617461[2]B601[3]20[3]02[3]08[14]40[2]402E64617461[3]50[4]30[3]02[3]0A[14]40[2]C0[472]E84D[3]50E8F702[2]558BEC83C4
C46A3C8D45C450FF7508E8D102[2]663B053C30400075218D35003040008D7DC40FB7C8F3A675118B4508A33E304000B8[4]C9
C20800B801[3]C9C20800558BEC83C4A4FCC745A4[4]6A3C6800304000E8A202[2]66A33C3040006AF5E89B02[2]8945FC6A0068
0B104000E85602[2]E82302[2]E84202[2]803E00752E0FB71D3C30400066C783003040000D0A664366436A00683C3040005368
00304000FF75FCE86002[2]E9B901[2]8BDE8BFE8A06463C3D74043C2C7504B020EB0A3C6172063C7A77022C2088074784C075
E08BF3813E53495A450F8585[3]8D45E650FF75FCE80502[2]668B45F4662B45F06640668945A4668B45F6662B45F266406689
45A683C604E8AD01[2]803E000F844E01[2]E84E01[2]6648668945F466C745F0[2]E88E01[2]803E000F842F01[2]E82F01[2]6648
668945F666C745F2[2]8D45F0506A01FF75FCE8AC01[2]E86101[2]803E000F840201[2]813E47504F537577C745A82C[3]8D45A8
50FF353E304000E85001[2]8B45C4668945A42945CC8B45C8668945A62945D083C604E81E01[2]803E000F84BF[3]E8BF[3]8945
C4E80801[2]803E000F84A9[3]E8A9[3]8945C86A01FF75D0FF75CCFF75C8FF75C4FF353E304000E80001[2]E983[3]813E475349
5A757B807E044575758D45D450FF353E304000E8CC[3]8B45DC668945A48B45E0668945A683C605E8A6[3]803E00744B66BB06
00813E4D494E00743066BB0300813E4D415800742466BB0900813E52455354741866BB[2]813E48494445740C66BB0500813E
53484F57750F6A006653FF353E304000E87E[3]8B45A4C9C333C032F68A164680FA20741084D2740C80EA30666BC00A6603C2
EBE84EC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCE871[3]8BF08A06463C2275098A06463C2275F9EB0C8A06463C20740484C075
F54EC38A06463C2074F94EC3CCFF2534204000FF2530204000FF252C204000FF2528204000FF2524204000FF2520204000FF
2500204000FF2518204000FF2514204000FF2510204000FF250C204000FF2508204000FF25042040[213]2221[2]9621[2]8A21[2]72
21[2]6221[2]4E21[2]3021[6]0821[2]FA20[2]E820[2]D220[2]C220[2]B420[6]9820[10]1621[2]2020[2]7820[10]A821[3]20[22]2221[2]96
21[2]8A21[2]7221[2]6221[2]4E21[2]3021[6]0821[2]FA20[2]E820[2]D220[2]C220[2]B420[6]CB00456E756D57696E646F777300E9
00476574436C69656E745265637400560147657457696E646F77506C6163656D656E74[2]5A0147657457696E646F77546578
7441[2]BE014D6F766557696E646F77[2]480253686F7757696E646F77[2]7573657233322E646C6C[2]9B004578697450726F63
65737300F500476574436F6E736F6C6553637265656E427566666572496E666F[2]F700476574436F6E736F6C655469746C65
41[2]6A0147657453746448616E646C65[2]7402536574436F6E736F6C6557696E646F77496E666F[2]F702577269746546696C
6500E600476574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[588]
Window.exe description wrote:Get or set some values related to console screen window.

Window
Show the window title.

Window Size [width height]
Set window size in characters.
At end, previous window size is returned as width+(height<<16) in ERRORLEVEL.

Window GSize [MIN|MAX|REST|HIDE|SHOW]
Set window graphic size or show state.
At end, previous window client-area size in pixels is returned as width+(height<<16) in ERRORLEVEL.

Window GPos [x y]
Set window position in pixels.
At end, return previous window position in pixels as x+(y<<16) in ERRORLEVEL.

Remember that MODE CON command get or set window Buffer size, and that window Screen size may be smaller or equal, but not larger than Buffer size. For example:

Code: Select all

Window Size
call :GetCoords Cols= Lines=
echo Current window SCREEN size is %Cols% columns X %Lines% lines
set Cols=
set Lines=
for /F "skip=2 tokens=2" %%a in ('mode con') do (
   if not defined Lines (
      set Lines=%%a
   ) else if not defined Cols (
      set Cols=%%a
   )
)
echo Current window BUFFER size is %Cols% columns X %Lines% lines
Output wrote:Current window SCREEN size is 80 columns X 43 lines
Current window BUFFER size is 80 columns X 300 lines

To change both sizes first change buffer size with MODE CON, then change screen size with Window Size; you may also change both window size and position in the same Window command giving Size and GPos parameters in that order. You may insert an equal-sign before the first value and a comma before the second one, if you wish. For example:

Code: Select all

@echo off
rem MOVEWINDOW.BAT - Example program of Window.exe auxiliary command
rem Antonio Perez Ayala

setlocal EnableDelayedExpansion

rem Define keyName=keyValue of used keys
for %%a in ("EnterKey=13" "DownArrow=-80" "LeftArrow=-75" "RightArrow=-77"       "UpArrow=-72"
            "Ctrl_DownArrow=-145" "Ctrl_LeftArrow=-115"   "Ctrl_RightArrow=-116" "Ctrl_UpArrow=-141"
            "Alt_DownArrow=-160"  "Alt_LeftArrow=-155"    "Alt_RightArrow=-157"  "Alt_UpArrow=-152" ) do (
   set %%a
)

rem Get window size, font size, and current window position
Window GSize
call :GetCoords GWinWidth= GWinHeight=
Window Size
call :GetCoords CWinCols=  CWinLines=
set /A GFontWidth=GWinWidth/CWinCols, GFontHeight=GWinHeight/CWinLines
Window GPos
call :GetCoords GWinX=     GWinY=

rem Grow window buffer to fit 1.5 times current wide
set Cols=
set Lines=
for /F "skip=2 tokens=2" %%a in ('mode con') do (
   if not defined Lines (
      set Lines=%%a
   ) else if not defined Cols (
      set Cols=%%a
   )
)
set /A Cols=Cols*3/2
mode con cols=%Cols% lines=%Lines%

echo/
echo - Arrow keys change window size.
echo - Ctrl-Arrow keys move window in character-wide steps.
echo - Alt-Arrow keys move window in one pixel steps.
echo/
echo Press Enter when ready

rem Define actions per key
rem (key values may directly be placed in indexes, but this way is clearer)
set action[%DownArrow%]=CWinLines+=1
set action[%UpArrow%]=CWinLines-=1
set action[%RightArrow%]=CWinCols+=1
set action[%LeftArrow%]=CWinCols-=1
set action[%Ctrl_DownArrow%]=GWinY+=GFontHeight
set action[%Ctrl_UpArrow%]=GWinY-=GFontHeight
set action[%Ctrl_RightArrow%]=GWinX+=GFontWidth
set action[%Ctrl_LeftArrow%]=GWinX-=GFontWidth
set action[%Alt_DownArrow%]=GWinY+=1
set action[%Alt_UpArrow%]=GWinY-=1
set action[%Alt_RightArrow%]=GWinX+=1
set action[%Alt_LeftArrow%]=GWinX-=1

:updateWindow
Window  Size=%CWinCols%,%CWinLines%  GPos=%GWinX%,%GWinY%

:nextKey
GetKey
if defined action[%errorlevel%] set /A !action[%errorlevel%]! & goto updateWindow
if %errorlevel% neq %EnterKey% goto nextKey
goto :EOF


:GetCoords Cols= Lines=
set /A "%1=%errorlevel%&0xFFFF, %2=(%errorlevel%>>16)&0xFFFF"
exit /B

I suggest you to test this program in a separated window this way: START MOVEWINDOW

When I began to write previous program, I got codes of the arrow keys this way: SHOWKEYCODES | FIND "Arrow" > MOVEWINDOW.BAT

Window GSize Hide command hide the window. A minimized or hidden window can not be cancelled via keyboard, and a hidden window can not be manually selected; the only way to recover a hidden window is via Window GSize Show. For example:

Code: Select all

@echo off
echo MINIMIZE the window for 5 seconds
echo (you can manually restore it)
pause
Window GSize Min
ping 127.0.0.1 -n 6 -w 1000 > NUL
Window GSize Rest
echo/
echo HIDE the window for 15 seconds
echo (you can NOT manually restore it^^!)
pause
Window GSize Hide
ping 127.0.0.1 -n 16 -w 1000 > NUL
Window GSize Show



6- CursorPos.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]55B5B8FD11D4D6AE11D4D6AE11D4D6AE9FCBC5AE18D4D6AEED
F4C4AE13D4D6AE5269636811D4D6AE[8]5045[2]4C010200EB84E24F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1C20[2]28[84]20[2]1C[27]2E74657874[3]4201[3]10[3]02[3]02[14]20[2]60
2E7264617461[2]F6[4]20[3]02[3]04[14]40[2]40[8]E806[3]50E81301[2]558BEC83C4E06AF5E81201[2]8945FC8D45E650FF75FCE8
FD[3]668B45EC668945E4E8BC[3]E8DB[3]803E0075058B45EAEB5C803E3D750646E8C6[3]668B4DEAE84A[3]8945EAE8B5[3]803E
007418803E2C750646E8A5[3]668B4DE4E829[3]668945EC8B5DEA53FF75FCE8AE[3]8D45E650536A018D45E350FF75FCE895[3]0F
B645E3C9C333C032DB33D28A164680FA2B740880FA2D750980CB0280CB018A164680FA30720F80FA39770A80EA306BC00A03
C2EBE9F6C301740BF6C302740366F7D86603C14EC3CCCCCCCCCCCCCCCCCCCCCCCCCCE847[3]8BF08A06463C2275098A06463C
2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2514204000FF2500204000FF2504204000FF250820
4000FF250C204000FF25102040[191]6E20[2]8C20[2]9C20[2]BA20[2]D620[2]6020[6]4420[10]E820[3]20[22]6E20[2]8C20[2]9C20[2]BA
20[2]D620[2]6020[6]9B004578697450726F6365737300F500476574436F6E736F6C6553637265656E427566666572496E666F
[2]6A0147657453746448616E646C65[2]380252656164436F6E736F6C654F757470757443686172616374657241006D025365
74436F6E736F6C65437572736F72506F736974696F6E[2]E600476574436F6D6D616E644C696E6541006B65726E656C33322E
646C6C[268]
CursorPos description wrote:Get or set cursor position.

CursorPos [[±]col [±]row]

If no parameter is given, return current cursor position as col+(row<<16) in ERRORLEVEL.

If any coordinate have sign, the position given is relative to the current one.

If cursor is moved, the Ascii code of the character at new position is returned in ERRORLEVEL.

You may insert an equal-sign before the first coordinate and a comma before the second one, if you wish. For example:

Code: Select all

CursorPos
call :GetCoords lastCol= lastRow=
CursorPos=%newCol%,%newRow%
echo Message at new position. Return cursor to original position:
CursorPos=%lastCol%,%lastRow%

If only one coordinate is given (with no sign), a position as col+(row<<16) is assumed; this feature makes simpler to return the cursor to a previous position:

Code: Select all

CursorPos
set lastPos=%errorlevel%
CursorPos=%newCol%,%newRow%
echo Message at new position. Return cursor to original position:
CursorPos %lastPos%

Previous feature also allows to modify both coordinates in a single operation this way:

Code: Select all

set /A "newPos=lastPos + deltaCol + (deltaRow<<16)"

If the cursor is moved to a screen buffer position that is not visible in the screen window, its contents is automatically scrolled to show the new cursor position; for example: cls & CursorPos 0 299

We may use this command for other things apart from show messages at any point in the screen. For example:

Code: Select all

@echo off
rem DRAWEQUATION.BAT - Draw simple equations y=f(x) in X-Y plane
rem Antonio Perez Ayala

setlocal EnableDelayedExpansion
set and=if

Window Size
call :GetCoords numCols= numLines=
set /A maxCol=numCols-1, maxLine=numLines-1

:get_f(x)
title MS-DOS - Draw Equation
color
cls
echo/
echo Enter the equation as an arithmetic expression that just use X and constants.
echo/
echo You may increase drawing precision by managing decimal places; to do that,
echo chose a number of decimals (ie: 2) and use it this way:
echo/
echo In the equation follow these rules:
echo - To add/sub constants to X, include decimals to them: X+3.00  X-2.00
echo - Mul/Div of X by a constant is correct (no decimals): X*5  X/4
echo - To multiply X-term by X-term, divide the product by "one": X*X/1.00
echo - To divide X-term by X-term, multiply first term by "one": X*1.00/X
echo/
echo Enter drawing limits with decimals: -6.00,5.80 or -110.00,130.00
echo/
echo For example, this equation: (x+4)(x+1)(x-3)
echo must be entered this way:   (x+4.00)*(x+1.00)/1.00*(x-3.00)/1.00
echo/
echo Or the equivalent polynomial: x^^3+2x^^2-11x-12
echo is entered this way: x*x/1.00*x/1.00+2*x*x/1.00-11*x-12
echo/

set Of(x)=
set /P "Of(x)=Enter equation: "
if not defined Of(x) goto endDraw
set "f(x)=!Of(x):.=!"

:get_Xaxis
echo/
set /P "axis=Enter X axis limits (left,right): "
for /F "tokens=1,2 delims=, " %%a in ("%axis%") do (
   set Oleft=%%a
   set Oright=%%b
)
set left=%Oleft:.=%
set right=%Oright:.=%
set /A "xStep=(right-left)/maxCol, right=left+xStep*numCols"
if %xStep% equ 0 echo Must be larger (%numCols% steps at least) & goto get_Xaxis

:get_Yaxis
echo/
set /P "axis=Enter Y axis limits (bottom,top): "
for /F "tokens=1,2 delims=, " %%a in ("%axis%") do (
   set Obottom=%%a
   set Otop=%%b
)
set bottom=%Obottom:.=%
set top=%Otop:.=%
set /A "yStep=(top-bottom)/maxLine"
if %yStep% equ 0 echo Must be larger (%numLines% steps at least) & goto get_Yaxis

title MS-DOS - Draw Equation - y=!Of(x)!
color 17
cls
if %left% lss 0 %and% %right% gtr 0 (
   set /A "xZero=(-left)/xStep, xZeroM1=xZero-1"
   Show Otop:-!xZeroM1! 32 124  13 10
   CursorPos !xZero! +0
   for /L %%y in (2,1,%maxLine%) do (
      Show "|"
      CursorPos -1 +1
   )
   Show 13  Obottom:-!xZeroM1! 32 124
)

if %bottom% lss 0 %and% %top% gtr 0 (
   set /A "yZero=maxLine+(bottom)/yStep, maxColDiv2=maxCol/2"
   CursorPos=0,!yZero!
   Show 45*%maxCol%  13 10
   Show Oleft
   CursorPos=!maxColDiv2!,+0
   Show Oright:-!maxColDiv2!
)

set x=%left%
for /L %%x in (0,1,%maxCol%) do (
   set /A "y=(Top-(%f(x)%))/yStep"
   if !y! lss 0 (
      CursorPos=%%x,0
      echo ^^
   ) else if !y! gtr %maxLine% (
      CursorPos=%%x,%maxLine%
      echo v
   ) else (
      CursorPos=%%x,!y!
      echo @
   )
   set /A x+=xStep
)
CursorPos=0,%maxLine%
Show "Press any key when ready"
GetKey
goto get_f(x)

:endDraw
title MS-DOS
goto :EOF


:GetCoords Cols= Lines=
set /A "%1=%errorlevel%&0xFFFF, %2=(%errorlevel%>>16)&0xFFFF"
exit /B

We may even draw trigonometric functions if we define a table of SIN(x) values multiplied by a standard factor (ie: 0xFFFF or 65535):

Code: Select all

:DefineSinTable

rem Definition of SIN table values (SIN(x)*65535) for 0-360 degrees
rem Antonio Perez Ayala

set Quad1=0
for %%a in ( 1144  2287  3430  4572  5712  6850  7987  9121 10252 11380 12505 13626 14742 15855 16962
            18064 19161 20252 21336 22415 23486 24550 25607 26656 27697 28729 29753 30767 31772 32768
            33754 34729 35693 36647 37590 38521 39441 40348 41243 42126 42995 43852 44695 45525 46341
            47143 47930 48703 49461 50203 50931 51643 52339 53020 53684 54332 54963 55578 56175 56756
            57319 57865 58393 58903 59396 59870 60326 60764 61183 61584 61966 62328 62672 62997 63303
            63589 63856 64104 64332 64540 64729 64898 65048 65177 65287 65376 65446 65496 65526 65535
           ) do (
   set /A Quad1+=1, Quad2=180-Quad1, Quad3=180+Quad1, Quad4=360-Quad1
   set SIN[!Quad1!]=%%a
   set SIN[!Quad2!]=%%a
   set SIN[!Quad3!]=-%%a
   set SIN[!Quad4!]=-%%a
)
for %%a in (0 180 360) do set SIN[%%a]=0

rem Additional values used in DRAWEQUATION.BAT (degrees must be multiple of 80)
set Quad5=360
for /L %%a in (1,1,40) do (
   set /A Quad5+=1
   set SIN[!Quad5!]=!SIN[%%a]!
)

for /L %%i in (1,1,5) do set Quad%%i=
exit /B

This way, to get SIN(x) multiplied by a number, just multiply the SIN[%x%] table value by the number and shift the result 16 bits to the right. This method correctly works with signed values because SET /A right shift operation is an aritmethic one (SAR), although the documentation indicate that is "logical shift" (SHR).

For example, to draw a simple SIN(x) graph, use DRAWEQUATION program above with these values:

Code: Select all

Enter equation: SIN[!x!]*20>>16
Enter X axis limits (left,right): 0 400
Enter Y axis limits (bottom,top): -21 21

It is interesting to note that in the evaluation of previous equation, the sustitution of variable values are performed three times in the same line:

0- Read the equation: f(x)=SIN[!x!]*20>>16
1- Normal %variable% expansion: set /A "y=%f(x)%" becomes: set /A "y=SIN[!x!]*20>>16"
2- Delayed !variable! expansion: set /A "y=SIN[!x!]*20>>16" becomes: set /A "y=SIN[1]*20>>16" (when x=1)
3- Replace variable values in SET /A command: set /A "y=1144*20>>16"

When CursorPos.exe move the cursor, the value returned in ERRORLEVEL is not the previous cursor position, as usual, but the Ascii code of the character in the screen at new cursor position. This feature makes possible that a program manage screen contents with no necessity for duplicate it in variables. This method is fast enough to develop some interactive animation programs, like a basic video-game:

Code: Select all

@echo off
rem SNAKE.BAT: Example of interactive animation - basic video-game program
rem Antonio Perez Ayala

setlocal EnableDelayedExpansion

rem Code for While support
if "%~1" equ "While" goto %2
set While=for /L %%? in () do if
set Do=(
set WEnd=) else exit
set RunWhile=cmd /Q /C "%~F0" While

rem Snake variables
set "SP= "
set Space=32
set Apple=64
set RightArrow=-77
set LeftArrow=-75
set /A "ToRight=1, ToLeft=-ToRight, ToDown=1<<16, ToUp=-ToDown"
set newPath[%ToRight%+%RightArrow%]=%ToDown%
set newPath[%ToRight%+%LeftArrow%]=%ToUp%
set newPath[%ToLeft%+%RightArrow%]=%ToUp%
set newPath[%ToLeft%+%LeftArrow%]=%ToDown%
set newPath[%ToDown%+%RightArrow%]=%ToLeft%
set newPath[%ToDown%+%LeftArrow%]=%ToRight%
set newPath[%ToUp%+%RightArrow%]=%ToRight%
set newPath[%ToUp%+%LeftArrow%]=%ToLeft%

rem Draw snake limits
Window Size
call :GetCoords numCols= numLines=
set /A numColsM2=numCols-2, numLinesM4=numLines-4
title MS-DOS - SNAKE.BAT - Right and Left arrow keys turns the snake
cls
Show 218 196*%numColsM2% 191
for /L %%a in (3,1,%numLines%) do (
   Show 179 SP:%numColsM2% 179
)
Show 192 196*%numColsM2% 217
CursorPos 0 0

rem Show initial snake and apple
CursorPos 8  20
Show 176 176 176
set /A "tailPos=8+(20<<16), headPos=10+(20<<16), nodeLen[0]=3, nodePath[0]=ToRight"
call :PutApple

rem Delay variable set initial speed:
set /A delay=30, delayStep=delay/8, growStep=0"

%RunWhile% AnimateSnake
title MS-DOS
CursorPos 0 %numLinesM4%
goto :EOF


:PutApple
set /A "Col=numCols*!random!>>15, Line=numLines*!random!>>15"
CursorPos %Col% %Line%
if %errorlevel% neq %Space% goto PutApple
Show %Apple%
exit /B


:AnimateSnake
set /A tail=0, tailPath=nodePath[0], tailDelay=0, head=0, headPath=nodePath[0], headDelay=0
set charAtHead=%Space%
%While% !charAtHead! equ %Space% %do%

   rem Get key and turn the snake
   GetKey /N
   for /F "tokens=1,2" %%a in ("!headPath! !errorlevel!") do (
      if defined newPath[%%a+%%b] (
         set headPath=!newPath[%%a+%%b]!
         set /A head+=1
         set /A nodeLen[!head!]=0, nodePath[!head!]=headPath, headDelay=0
      )
   )

   rem If snake must move: do it
   set /A headDelay-=1
   if !headDelay! leq 0 (

      rem Advance head, show head
      set /A headPos+=headPath, nodeLen[!head!]+=1
      CursorPos !headPos!
      set charAtHead=!errorlevel!
      Show 176

      rem If apple eated: put new apple, speed up snake and set it to grow
      if !charAtHead! equ !Apple! (
         Show 7
         call :PutApple
         if !delay! gtr 0 set /A delay-=delayStep
         set /A growStep+=1, tailDelay=growStep, charAtHead=Space
      )

      rem Clear tail, advance tail
      if !tailDelay! equ 0 (
         CursorPos !tailPos!
         Show 32
         set /A nodeLen[!tail!]-=1, aux=nodeLen[!tail!]
         if !aux! equ 0 (
            set nodeLen[!tail!]=
            set nodePath[!tail!]=
            set /A tail+=1
            set /A tailPath=nodePath[!tail!]
         )
         set /A tailPos+=tailPath
      ) else (
         rem Let the snake to grow
         set /A tailDelay-=1
      )

      set headDelay=%delay%
   )
%WEnd%
exit /B


:GetCoords Cols= Lines=
set /A "%1=%errorlevel%&0xFFFF, %2=(%errorlevel%>>16)&0xFFFF"
exit /B


Have fun! 8)

Antonio
Last edited by Aacini on 30 Jun 2012 04:54, edited 5 times in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#4 Post by Ed Dyreen » 20 Jun 2012 23:53

'
Really need to learn the x86 instruction set somedayZzz... :oops:

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#5 Post by Aacini » 21 Jun 2012 18:17

Ed Dyreen wrote:Abra cadabra :P I like the getkey :D
Thanks a lot, Ed! :)
Ed Dyreen wrote:Really need to learn the x86 instruction set somedayZzz... :oops:
Yes, it is the way to do some "magic" (not by sleight of hand) :wink:


I made a couple minor corrections to above programs; if you copied some of the programs below, you should complete these changes:

- In MOVEWINDOW.BAT @ line 8: "set keyName=", delete the line.

- In DefineSinTable subroutine, before "exit /B", insert this line:

Code: Select all

for /L %%i in (1,1,5) do set Quad%%i=

- In SNAKE.BAT program, under "rem Clear tail, advance tail" section, between these two lines:

Code: Select all

         if !aux! equ 0 (
            set /A tail+=1
insert these ones:

Code: Select all

            set nodeLen[!tail!]=
            set nodePath[!tail!]=

These are minor changes that have not major effects; they delete variables that will not be used again. I documented the changes here because someone could note them.


:arrow: An interesting change that will improve SNAKE game is the addition of some random "walls" that make snake movement more difficult. The walls could be larger and/or more numerous depending on the number of apples the snake ate in the last game (given by growStep variable). Wants someone to achieve this change perhaps? :roll: I am very busy right now preparing the following sleights of hand... 8)

Antonio

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#6 Post by Aacini » 24 Jun 2012 17:46

I added optional parameters to Window GSize command that allows to minimize, maximize and restore a window; also, there are two additional parameters that allows to Hide and Show a window. An interesting feature of these new parameters is that a hidden window can not be manually cancelled! For further details, see Window.exe command description above.

Antonio

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#7 Post by Aacini » 04 Jul 2012 00:46

7- StdTime.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]55917B8611F015D511F015D511F015D59FEF06D51BF015D5ED
D007D513F015D55269636811F015D5[8]5045[2]4C01030087A8EF4F[8]E0000F010B01050C0004[3]04[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]40[3]04[6]03[5]10[2]10[4]10[2]10[6]10[11]2020[2]28[84]20[2]20[27]2E74657874[3]E802[3]10[3]04[3]04[14]20[2]60
2E7264617461[2]E6[4]20[3]02[3]08[14]40[2]402E64617461[3]30[4]30[3]02[3]0A[14]40[2]C0[480]E806[3]50E8B302[2]558BEC83C4A8
6AF5E8B802[2]8945B0C745A8[4]FCE86802[2]E88702[2]803E00750E8D45DC50E88902[2]E9DF[3]E82302[2]84D20F846C01[2]80
FA200F846301[2]668945E446E80802[2]668945E666C745E8[2]66C745EA[2]84D2747E80FA20742C46E8E901[2]668945E884D2
746B80FA20741946E8D601[2]6683F8647D04B10AF6E1668945EA803E00744DE80A02[2]803E0074436A148D45EC506A23680004
[2]E80902[2]807DEC30752B6A148D45EC506A29680004[2]E8F101[2]8A063A45EC7512668345E40C66837DE418750666C745E4
[2]66837DE4170F876601[2]66837DE63B0F875B01[2]66837DE83B0F875001[2]66817DEAE7030F874401[2]668B45E4D40A6605
303086C466A305304000668B45E6D40A6605303086C466A30D304000668B45E8D40A6605303086C466A315304000668B45EA
B264F6F20430A21E3040008AC4D40A6605303086C466A31F3040006A008D45AC506823[3]6800304000FF75B0E85001[2]0FB7
45E4B93C[3]66F7E1660345E6F7E10FB755E803C2B9E803[2]F7E10FB755EA03C28945A8E9AA[3]33D2B9E803[2]F7F1668955EA
B93C[3]33D2F7F1668955E833D2F7F1668955E6668945E4BB0C[3]803E007415E8C6[3]66813E2F4C740766813E2F6C750233DB
6A288D45B4506A008D45DC5053680004[2]E8C1[3]6685C074200FB7D86636C7442BB40D0A43436A008D45AC50538D45B450FF
75B0E8A2[3]0FB745E4B964[3]F7E10FB75DE603C3F7E10FB75DE803C3B9E803[2]F7E10FB75DEA03C38945A88B45A8C9C333C0
33D28A164680FA30720F80FA39770A80EA306BC00A03C2EBE94EC3CCCCCCCCCCCCCCCCCCCCCCE84D[3]8BF08A06463C227509
8A06463C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2518204000FF2500204000FF2504204000FF
2508204000FF250C204000FF2510204000FF25142040[281]7620[2]8620[2]9820[2]A820[2]BA20[2]C620[2]6820[6]4820[10]D820[3]20
[22]7620[2]8620[2]9820[2]A820[2]BA20[2]C620[2]6820[6]9B004578697450726F636573730029014765744C6F63616C54696D65
[2]2A014765744C6F63616C65496E666F41[2]6A0147657453746448616E646C65[2]8E0147657454696D65466F726D617441[2]F7
02577269746546696C6500E600476574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[284]486F75723D68680D
0A4D696E3D6D6D0D0A5365633D73730D0A4D5365633D6D73650D0A[477]
StdTime.exe description wrote:Get standard time fields and convert they to/from number of milliseconds.

StdTime [time|milliseconds [/L]]

Show the value of Hour, Min, Sec and MSec fields of the time given in locale format;
if no parameter is given, current time is used.
All fields shown will have left zeros if needed to fill their widths.
At end, return the equivalent number of milliseconds in ERRORLEVEL.
If the given time is invalid, nothing is shown and return zero.

If the parameter is a plain number with no time separators, a number of milliseconds
is assumed; in this case, show the equivalent time in standard 24-hour format
(ie: HH:MM:SS) and return it as HHMMSSmmm decimal value in ERRORLEVEL.
If /L switch is also given, use 12-hour am/pm format to show the time.

Examples.

Create a file with current time as name in HH-MM-SS.txt format:

Code: Select all

for /F %%a in ('StdTime') do set %%a
echo Some data > %Hour%-%Min%-%Sec%.txt

Show the future time 1:30 hours ahead current one (in same day):

Code: Select all

StdTime > NUL
set current=%errorlevel%
StdTime 1:30 > NUL
set /A futureTime=current+%errorlevel%
StdTime %futureTime% /L

List files modified in the last 3 hours (in same day):

Code: Select all

@echo off
setlocal EnableDelayedExpansion
StdTime > NUL
set current=%errorlevel%
StdTime 3:00 > NUL
set /A pastTime=current-%errorlevel%
for %%a in (*.*) do (
   for /F "tokens=1*" %%b in ("%%~Ta") do (
      if %%b equ %date% (
         StdTime %%c > NUL
         if !errorlevel! gtr %pastTime% echo %%a
      )
   )
)

To get elapsed times, get the time at start and end of the process and subtract them:

Code: Select all

StdTime > NUL
set start=%errorlevel%
process to time goes here...
StdTime > NUL
set elapsed=%errorlevel%-start
The elapsed time is given in milliseconds; the subroutine below display this value in a readable format:

Code: Select all

:ElapsedTime milliseconds
setlocal EnableDelayedExpansion
StdTime %1 > NUL
rem ERRORLEVEL=HHMMSSmmm
set mmm=%errorlevel:~-3%
set HHMMSS=%errorlevel:~0,-3%
if defined HHMMSS (
   set SS=%HHMMSS:~-2%
   set HHMM=%HHMMSS:~0,-2%
   if defined HHMM (
      set MM=!HHMM:~-2!
      set HH=!HHMM:~0,-2!
      if defined HH (
         set result=!HH!:!MM!:!SS!.%mmm% Hours
      ) else (
         set result=!MM!:!SS!.%mmm% Minutes
      )
   ) else (
      set result=!SS!.%mmm% Seconds
   )
) else (
   set result=%mmm% Milliseconds
)
echo %result%
exit /B



8- StdDate.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]55917B8611F015D511F015D511F015D59FEF06D51BF015D5ED
D007D513F015D55269636811F015D5[8]5045[2]4C01030092DEF34F[8]E0000F010B01050C0004[3]04[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]40[3]04[6]03[5]10[2]10[4]10[2]10[6]10[11]2020[2]28[84]20[2]20[27]2E74657874[3]C803[3]10[3]04[3]04[14]20[2]60
2E7264617461[2]E6[4]20[3]02[3]08[14]40[2]402E64617461[3]30[4]30[3]02[3]0A[14]40[2]C0[480]E806[3]50E89303[2]558BEC83C4B4
6AF5E89E03[2]8945BCC745B4[4]E84903[2]E86803[2]803E00750E8D45EC50E87003[2]E91E01[2]6A028D45FE506A21680004[2]E8
5F03[2]807DFE307538E8EA02[2]84D20F84C701[2]80FA200F84BE01[2]668945EE46E8CF02[2]84D20F84C202[2]668945F246E8
BD02[2]668945ECEB74807DFE317538E8AC02[2]84D20F848901[2]80FA200F848001[2]668945F246E89102[2]84D20F848402[2]66
8945EE46E87F02[2]668945ECEB36E87402[2]84D20F845101[2]80FA200F844801[2]668945EC46E85902[2]84D20F844C02[2]66
8945EE46E84702[2]668945F2668B45EC6685C00F843102[2]66BA030022D0751566B9640066F7F184D2750424037506FE051B
3040000FB75DEE6685DB0F840702[2]6683FB0C0F87FD01[2]668B45F26685C00F84F001[2]3A83193040000F87E401[2]668B45
EC66C745EA0A00B904[3]6633D266F775EA80C230C1E3088ADAE2EF891D05304000668B45EED40A6605303086C466A30E3040
00668B45F2D40A6605303086C466A3153040006A008D45B8506819[3]6800304000FF75BCE8FD01[2]66837DEE037D09668345
EE0C66FF4DEC0FB75DF280C302668B45EE664066B9320166F7E166B90A0066F7F16603D86633D2668B45EC66B9640066F7F1
662BD866C1E8026603D80FB745EC66056C12B9AD8E[2]F7E1B964[3]F7F103D881EBF405[2]895DB4E91601[2]05D90B01008BD8
C1E002B9B13A020033D2F7F18BF883E831B964[3]F7E1668945EC8BC7B9B13A0200F7E183C003C1E8022BD88BC340B9A00F[2]F7
E1B9094B1600F7F1660145ECB9B505[2]F7E1C1E8022BD883C31F8BC3B950[3]F7E1B98F09[2]F7F18BF8F7E1B950[3]F7F12BD8
66895DF28BC7B90B[3]33D2F7F1660145ECB90C[3]F7E12BF8668BC76683C002668945EEBB01[3]803E007418E8BE[3]66813E2F
4C740766813E2F6C7505BB02[3]6A288D45C2506A008D45EC5053680004[2]E8A4[3]6685C074200FB7D86636C7442BC20D0A43
436A008D45B850538D45C250FF75BCE897[3]0FB745ECB964[3]F7E10FB75DEE03C3F7E10FB75DF203C38945B48B45B4C9C333
C033D28A164680FA30720F80FA39770A80EA306BC00A03C2EBE94EC3CCCCCCCCCCCCCCCCCCCCCCCCCCE84D[3]8BF08A06463C
2275098A06463C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2518204000FF2500204000FF2504
204000FF2508204000FF250C204000FF2510204000FF25142040[57]7620[2]8820[2]9820[2]AA20[2]BA20[2]C620[2]6820[6]4820
[10]D820[3]20[22]7620[2]8820[2]9820[2]AA20[2]BA20[2]C620[2]6820[6]9B004578697450726F6365737300040147657444617465
466F726D617441[2]29014765744C6F63616C54696D65[2]2A014765744C6F63616C65496E666F41[2]6A014765745374644861
6E646C65[2]F702577269746546696C6500E600476574436F6D6D616E644C696E6541006B65726E656C33322E646C6C[284]5959
59593D797979790D0A4D4D3D6D6D0D0A44443D64640D0A001F1C1F1E1F1E1F1F1E1F1E1F[474]
StdDate description wrote:Get standard date fields and convert they to/from Julian Day Number.

StdDate [date|jdn [/L]]

Show the value of YYYY, MM and DD fields of the date given in locale format;
if no parameter is given, current date is used.
MM and DD fields shown will have a left zero if the value is less than 10.
At end, return the equivalent Julian Day Number in ERRORLEVEL.
If the given date is invalid, nothing is shown and return zero.

If the parameter is a plain number with no date separators, a Julian Day Number
is assumed; in this case, show the equivalent date in standard locale format
(ie: MM/DD/YYYY) and return it as YYYYMMDD decimal value in ERRORLEVEL.
If /L switch is also given, use long format to show the date.

In the examples below MM/DD/YYYY date format is assumed. If your locale is different, use the appropiate format when enter the example date values.

Get and show current day of week (0=Sunday, 1=Monday, ...):

Code: Select all

StdDate > NUL
set /A dow=(%errorlevel%+1)%%7
rem Show day of week (short form) with the date
set /A dow*=3
set DaysOfWeek=SunMonTueWedThuFriSat
echo !DaysOfWeek:~%dow%,3!, %date%

Show current date in long format:

Code: Select all

StdDate > NUL
StdDate %errorlevel% /L

Create a directory with current date as name in YYYY-MM-DD format:

Code: Select all

for /F %%a in ('StdDate') do set %%a
md %YYYY%-%MM%-%DD%

List files older than 30 days:

Code: Select all

@echo off
setlocal EnableDelayedExpansion
StdDate > NUL
set current=%errorlevel%
for %%a in (*.*) do (
   StdDate %%~Ta > NUL
   set /A daysOld=current-!errorlevel!
   if !daysOld! gtr 30 echo %%a
)
On January 8, 1994 Russian cosmonaut, Valeri Polyakov, was launched in Soyuz TM-18 mission to MIR space station. Some technical problems avoided him to be rotated when next mission arrived MIR, so he must stayed there waiting for the following one, Soyuz TM-20, making his spaceflight the longest one for a human being: 437 days. When Polyakov returned to Earth?

Code: Select all

StdDate 1/8/1994 > NUL
set /A return=%errorlevel%+437
StdDate %return%

03/21/1995
The "Thousand Days War" was a civil armed conflict in the newly created Republic of Colombia and the then province, Panama, that begun on October 17th, 1899 and ended on November 21, 1902. How many days that war really lasts?

Code: Select all

StdDate 10/17/1899 > NUL
set start=%errorlevel%
StdDate 11/21/1902 > NUL
set /A days=%errorlevel%-start
echo %days%

1130
Although the next subroutine does not use StdDate program, it is included here to complete date-related examples.

Code: Select all

:EasterSunday year
rem Calculate the date of Christian Easter Sunday of any given year
rem Antonio Perez Ayala
set /A A=%1%%19, B=%1/100, C=%1%%100, D=B/4, E=B%%4, F=(B+8)/25, G=(B-F+1)/3, H=(A*19+B-D-G+15)%%30, I=C/4
set /A K=C%%4, L=((E+I)*2-H-K+32)%%7, M=(A+H*11+L*22)/451, N=H+L-M*7+114, Month=N/31, Day=N%%31+1
echo %Month%/%Day%/%1

Previous method first appeared in "Butcher's Ecclesiastical Calendar" on 1876, but was reprinted on 1981 in "Practical Astronomy with your Calculator, 2nd Edition", Peter Duffett-Smith, Cambridge University Press. For example, Easter Sunday of year 2013 is March 31.


These auxiliary programs should solve all time and date locale related problems; however, I can test they just with my own locale (DD/MM/YYYY). Please, test these programs and report any problem you may encounter. I appreciate it if you report that the programs works correctly in YYYY/MM/DD date format or with "p.m." time indicator in other languages.


Antonio

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#8 Post by Aacini » 08 Jul 2012 21:28

9- Ascii.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]5527D9C81146B79B1146B79B1146B79B9F59A49B1946B79BED
66A59B1346B79B526963681146B79B[8]5045[2]4C0102006C3BF64F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1820[2]28[84]20[2]18[27]2E74657874[3]DC01[3]10[3]02[3]02[14]20[2]60
2E7264617461[2]BC[4]20[3]02[3]04[14]40[2]40[8]E806[3]50E8B301[2]558BEC81C4ECDFFFFFC785ECDFFFFF[4]6AF5E8A501[2]89
45FC8DBDFCDFFFFF89BDF8DFFFFFE85701[2]E87601[2]8A064684C00F84A2[3]3C22751D8A064684C00F8493[3]3C2274058807
47EBEC8A06463C2274F4EBCF2BBDF8DFFFFF741B01BDECDFFFFF8D85F0DFFFFF50FFB5F8DFFFFFFF75FCE8AB[3]8BFE4F8A06
8885F7DFFFFF3C20740784C0740346EBEDC60600680020[2]FFB5F8DFFFFF57E80D01[2]85C0741D8BF801BDECDFFFFF8D85F0
DFFFFF50FFB5F8DFFFFFFF75FCE860[3]8A85F7DFFFFF88068BBDF8DFFFFFE94EFFFFFF2BBDF8DFFFFF741B01BDECDFFFFF8D
85F0DFFFFF50FFB5F8DFFFFFFF75FCE82A[3]66C785FCDFFFFF0D0A6A008D85F0DFFFFF506A02FFB5F8DFFFFFFF75FCE8A0[3]8B
85ECDFFFFFC9C3558BEC568BCF8B750C03FE57B264660FB60646F6F284C0750A8AC4D40A84E4750BEB0F04308807478AC4D4
0A80C4308827470430880747C6072047E2D15B2BFB6A00FF75105753FF7508E849[3]5EC9C20C00CCCCCCCCE841[3]8BF08A06
463C2275098A06463C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3CCFF2510204000FF2500204000FF
2504204000FF2508204000FF250C2040[37]6620[2]8020[2]9020[2]9C20[2]5820[6]4020[10]AE20[3]20[22]6620[2]8020[2]9020[2]9C
20[2]5820[6]9B004578697450726F63657373001301476574456E7669726F6E6D656E745661726961626C6541006A01476574
53746448616E646C65[2]F702577269746546696C6500E600476574436F6D6D616E644C696E6541006B65726E656C33322E64
6C6C[326]
Ascii.exe description wrote:Show Ascii codes of string literals and Batch variables.

Ascii "literal" | variable ...

At end, the number of characters converted is returned in ERRORLEVEL.



10- CursorSize.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]5527D9C81146B79B1146B79B1146B79B9F59A49B1946B79BED
66A59B1346B79B526963681146B79B[8]5045[2]4C01020033F0D84F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1820[2]28[84]20[2]18[27]2E74657874[3]EC[4]10[3]02[3]02[14]20[2]602E
7264617461[2]C6[4]20[3]02[3]04[14]40[2]40[8]E806[3]50E8C3[3]558BEC83C4F06AF5E8C2[3]8945FC8D45F450FF75FCE8AD[3]8B
45F4837DF801740233C08945F0E866[3]E885[3]803E00745266813E2F4C740766813E2F6C7509C745F801[3]EB2F33DB33C08A
06463C30720D3C3977092C306BDB0A03D8EBEC85DB740C895DF4C745F801[3]EB07C745F8[4]8D45F450FF75FCE84A[3]8B45F0
C9C3CCCCCCCCCCE841[3]8BF08A06463C2275098A06463C2275F9EB0C8A06463C20740484C075F54EC38A06463C2074F94EC3
CCFF2510204000FF2500204000FF2504204000FF2508204000FF250C2040[277]6620[2]7E20[2]8E20[2]A620[2]5820[6]4020[10]B8
20[3]20[22]6620[2]7E20[2]8E20[2]A620[2]5820[6]9B004578697450726F6365737300EF00476574436F6E736F6C65437572736F
72496E666F[2]6A0147657453746448616E646C65[2]6C02536574436F6E736F6C65437572736F72496E666F[2]E60047657443
6F6D6D616E644C696E6541006B65726E656C33322E646C6C[316]
CursorSize.exe description wrote:Get or set cursor size.

CursorSize [size|/L]

The cursor size is a percentage (1..100) of the character cell that is filled by the cursor.
Use 0 to hide the cursor; use /L to recover the last hidden cursor.

At end, the previous cursor size is returned in ERRORLEVEL.

Example:

Code: Select all

rem Grow the cursor to a square ("insert" mode)
CursorSize 70
set lastSize=%errorlevel%
set /P "newChars=Insert new characters: "
rem Recover original cursor
CursorSize %lastSize%



The following Batch subroutine define several values useful to write color attributes:

Code: Select all

:DefineColorCodes
set HexDigit=0123456789ABCDEF
set c=-1
for %%c in ( Black Blue  Green  Aqua  Red  Purple  Brown  White
             Grey  LBlue LGreen LAqua LRed LPurple Yellow BWhite ) do (
   set /A c+=1
   for %%C in (!c!) do set %%c=!HexDigit:~%%C,1!
)
exit /B



11- TextColor.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B0[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]55B5B8FD11D4D6AE11D4D6AE11D4D6AE9FCBC5AE18D4D6AEED
F4C4AE13D4D6AE5269636811D4D6AE[8]5045[2]4C010200A7F8D84F[8]E0000F010B01050C0002[3]02[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10[4]10[2]10[6]10[11]1C20[2]28[84]20[2]1C[27]2E74657874[3]0201[3]10[3]02[3]02[14]20[2]60
2E7264617461[2]E6[4]20[3]02[3]04[14]40[2]40[8]E806[3]50E8D3[3]558BEC83C4E4C745FCF5FFFFFFE893[3]E8B2[3]66813E2F45
740766813E2F65750EC745FCF4FFFFFF4646E896[3]FF75FCE8AA[3]8945FC8D45E650FF75FCE88F[3]803E0074398A0646E837
[3]660FB6D88A063C20740E84C0740AE824[3]C0E3040AD86A006653FF75FCE870[3]85C07509E85B[3]F7D8C9C30FB745EEC9C3
2C303C0976082C073C0F76022C1FC3CCCCCCCCCCCCCCCCE847[3]8BF08A06463C2275098A06463C2275F9EB0C8A06463C2074
0484C075F54EC38A06463C2074F94EC3CCFF2514204000FF2500204000FF2504204000FF2508204000FF250C204000FF2510
2040[255]6E20[2]8C20[2]9C20[2]AC20[2]C620[2]6020[6]4420[10]D820[3]20[22]6E20[2]8C20[2]9C20[2]AC20[2]C620[2]6020[6]9B0045
78697450726F6365737300F500476574436F6E736F6C6553637265656E427566666572496E666F[2]28014765744C61737445
72726F72[2]6A0147657453746448616E646C65[2]7102536574436F6E736F6C655465787441747472696275746500E6004765
74436F6D6D616E644C696E6541006B65726E656C33322E646C6C[284]
TextColor.exe description wrote:Get or set text color.

TextColor [/E] [bf]

Set text color that will be used in posterior output to STDOUT standard handle.

If /E switch is given, set the color of STDERR standard handle.

<bf> is a color attribute (see COLOR /? for more info).

At end, the previous text color of that handle is returned in ERRORLEVEL.

For example, to execute a program so normal output appear in white text on blue background, and error output appear in yellow text on red background:

Code: Select all

TextColor %Blue%%White%
set lastColor=%errorlevel%
TextColor /E %Red%%Yellow%
rem place here any program, for example:
echo This is a normal message
echo This is an ERROR message >&2
TextColor %lastColor%
TextColor /E %lastColor%

NOTE: TextColor.exe program may not work in certain computers (like my own!) :cry: ; in this case, it returns a negative error code in ERRORLEVEL (in my computer the error code is -998). Even if the program runs correctly, text output may occasionally present color errors (like this one). It seems that program fails when the video hardware is not entirely compatible (ie: some laptops), and that posterior color errors are related to window buffer size vs. screen size. We need a more complete tests on this matter...


EDIT: I slightly modified ColorShow.exe program to also accept an X-letter instead an asterisk in CODExTIMES parameter.

12- ColorShow.exe.hex:

Code: Select all

4D5A900003[3]04[3]FFFF[2]B8[7]40[35]B8[3]0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F74
2062652072756E20696E20444F53206D6F64652E0D0D0A24[7]5549FA721128942111289421112894219F3787211A289421ED
088621132894215269636811289421[16]5045[2]4C0103001DDBEB50[8]E0000F010B01050C0006[3]04[7]10[3]10[3]20[4]40[2]10
[3]02[2]04[7]04[8]40[3]04[6]03[5]10[2]10[4]10[2]10[6]10[11]2420[2]28[84]20[2]24[27]2E74657874[3]DE04[3]10[3]06[3]04[14]20[2]60
2E7264617461[2]3201[3]20[3]02[3]0A[14]40[2]402E64617461[3]20[4]30[3]02[3]0C[14]40[2]C0[472]E806[3]50E8A304[2]558BEC81C4
E8DFFFFFFC6AF5E8A404[2]8945FC6800304000FF75FCE88804[2]8B1D043040008D85E8DFFFFF50536A018D45FA50FF75FCE8
7E04[2]668B45FA66A316304000D41086C4D510668945F88DBDF8DFFFFF89BDF4DFFFFFE81304[2]E83204[2]8A064684C00F84
4803[2]3C2F0F858C[3]2BBDF4DFFFFF74186A008D85E8DFFFFF5057FFB5F4DFFFFFFF75FCE85F03[2]8BBDF4DFFFFF8A064684
C00F840F03[2]3C20750C668B45FA66A316304000EBA73C2F750C668B45F866A316304000EB972C303C0976082C073C0F7602
2C208A264684E40F84D602[2]80FC20741286C42C303C0976082C073C0F76022C20D51066A316304000E95CFFFFFF3C227520
8A064684C00F84A502[2]3C227405880747EBEC8A06463C2274F4E938FFFFFF3C300F82C6[3]3C390F87BE[3]E8A102[2]3C2A74
083C5874043C7875278ADC468A06463C300F826102[2]3C390F875902[2]E87A02[2]0FB6CC8AC3F3AAE9F0FEFFFF80FC207379
80FC09751F8B0D0430400003CF2B8DF4DFFFFF83E10783E908F7D9B020F3AAE9C7FEFFFF2BBDF4DFFFFF741A506A008D85E8
DFFFFF5057FFB5F4DFFFFFFF75FCE83D02[2]588BBDF4DFFFFF88276A008D85E8DFFFFF506A01FFB5F4DFFFFFFF75FCE8E302
[2]6800304000FF75FCE8BE02[2]E972FEFFFF882747E96AFEFFFF2BBDF4DFFFFF74186A008D85E8DFFFFF5057FFB5F4DFFFFF
FF75FCE8E101[2]8BFE4F33DB889DF2DFFFFF8A063C3A74118885F3DFFFFF3C20746084C0745C46EBE9889DF2DFFFFFC6060046
8A06463C2D7509C685F2DFFFFF02EB0B3C2B750AC685F2DFFFFF018A06463C300F827001[2]3C390F876801[2]E86901[2]8885
F3DFFFFF3C20740884C00F855101[2]84E40F841001[2]8ADCC60600680020[2]8D85F8DFFFFF5057E80702[2]85C00F84F1[3]85
DB0F84CF[3]3BC30F84C7[3]7C2D80BDF2DFFFFF00741DF685F2DFFFFF01750A2BC30185F4DFFFFFEB0A2BC3D1E80185F4DFFF
FF8BC3E998[3]2BD88BBDF4DFFFFF03F889BDECDFFFFF50B0208BCBF3AA80BDF2DFFFFF007443F685F2DFFFFF02741C6A018D
85E8DFFFFF5053FFB5ECDFFFFFFF75FCE8C9[3]33DBEB1E8BFBD1EF2BDF6A018D85E8DFFFFF5057FFB5ECDFFFFFFF75FCE8A7
[3]588BF86A018D85E8DFFFFF5057FFB5F4DFFFFFFF75FCE88C[3]6A028D85E8DFFFFF5053FFB5ECDFFFFFFF75FCE874[3]EB1A
8BF86A008D85E8DFFFFF5057FFB5F4DFFFFFFF75FCE858[3]8A85F3DFFFFF88068DBDF8DFFFFF89BDF4DFFFFFE9A8FCFFFF2B
BDF4DFFFFF74186A008D85E8DFFFFF5057FFB5F4DFFFFFFF75FCE81F[3]0FB745FAC9C3240F8AE08A06463C30720C3C397708
2C30D50A8AE0EBED4EC3558BEC6A00FF7514FF7510FF750CFF7508E8B2[3]8B4D1066837D180172137708010D18304000EB46
030D18304000894D10578B7D0C66A116304000F366AB8B0D04304000FF751451FF7510FF750CFF7508E876[3]5F6800304000FF
7508E84A[3]C705183040[5]C9C21400CCCCCCCCCCCCCCCCE853[3]8BF08A06463C2275098A06463C2275F9EB0C8A06463C2074
0484C075F54EC38A06463C2074F94EC3CCFF2500204000FF2504204000FF2508204000FF250C204000FF2510204000FF2514
204000FF2518204000FF251C2040[291]7020[2]7E20[2]9C20[2]B620[2]C620[2]E420[2]F420[2]1221[6]4C20[10]2421[3]20[22]7020[2]7E
20[2]9C20[2]B620[2]C620[2]E420[2]F420[2]1221[6]9B004578697450726F6365737300F500476574436F6E736F6C6553637265
656E427566666572496E666F[2]1301476574456E7669726F6E6D656E745661726961626C6541006A0147657453746448616E
646C65[2]370252656164436F6E736F6C654F7574707574417474726962757465[2]EE025772697465436F6E736F6C654100F2
025772697465436F6E736F6C654F757470757441747472696275746500E600476574436F6D6D616E644C696E6541006B6572
6E656C33322E646C6C[720]
ColorShow.exe description wrote:Show characters in color.

ColorShow /bf showParam ...

/bf Specify a color attribute (see COLOR /? for more info)
showParam Specify the characters to show (see Show.exe program description)

ColorShow.exe show characters in the same way of Show.exe program, but in color.

Color attributes may be inserted at any place in the show parameters, setting the color
of following parameters. If the first show parameter has not a previous attribute, the
color of initial cursor position is used. Use / alone to indicate the color of initial
cursor position, use // to indicate the initial color attribute in reverse video.

At end, the original attribute of initial cursor position is returned in ERRORLEVEL .

Examples:

Code: Select all

ColorShow /%Blue%%White% "White on blue" CR LF /%Yellow% "Yellow on black" CR LF

set HexDigit=0123456789ABCDEF
ColorShow
set /A "text=%errorlevel%&0xF, back=%errorlevel%>>4"
echo Attribute of original cursor position: !HexDigit:~%back%,1!!HexDigit:~%text%,1!
The following Batch subroutine allows to select one of several options in one line.

Code: Select all

@echo off

:Select [/bf] "prompt" [/bf] option1 option2 ...
rem Antonio Perez Ayala

if "%~1" neq "" goto begin
:usage
echo Activate a selection of options in one line.
echo/
echo call :Select [/bf] "prompt" [/bf] option1 option2 ...
echo/
echo Prompt must be enclosed in quotes; use "" if prompt not wanted.
echo/
echo /bf specify attribute(s) used in next parameters, option in focus will be shown
echo in reversed attribute. If attribute not given, current position color is used.
echo/
echo Options may be simple words or "Several words in quotes"; the first digit or
echo uppercase letter in an option may be used to select it with just one key.
echo/
echo At end, the number of the selected option is returned in ERRORLEVEL.
goto :EOF

:begin
setlocal EnableDelayedExpansion

rem Define auxiliary variables
set name=
for %%a in (RightArrow=-77 LeftArrow=-75 Ctrl_RightArrow=-116 Ctrl_LeftArrow=-115 ) do (
   if not defined name (
      set name=%%a
   ) else (
      set action[%%a]=!name!
      set name=
   )
)
set EnterKey=13
set Digit0=48
set UpcaseZ=90
set LowcaseA=97
set HexDigit=0123456789ABCDEF

rem Show prompt with given, or current, attribute
set "attrib=%~1"
shift
if %attrib:~0,1% equ / (
   ColorShow %attrib% %1 / " "
   shift
) else (
   ColorShow "%attrib% "
   set attrib=
)

rem Get given, or current, attribute for options
set "attrib2=%~1"
if %attrib2:~0,1% equ / (
   set attrib=%attrib2%
   shift
)
if defined attrib goto getFocusAttrib
ColorShow
set /A "text=%errorlevel%&0xF, back=%errorlevel%>>4"
set attrib=/!HexDigit:~%back%,1!!HexDigit:~%text%,1!
:getFocusAttrib
set focusAttrib=/%attrib:~2,1%%attrib:~1,1%

rem Get options
set lastOpt=0
:nextOption
   set /A lastOpt+=1
   set option[%lastOpt%]=%~1
   CursorPos
   set position[%lastOpt%]=%errorlevel%
   ColorShow %attrib% "%~1" / " "
   for /F "delims=" %%a in ('Ascii "%~1"') do (
      for %%b in (%%a) do (
         if %%b geq %Digit0% if %%b leq %UpcaseZ% (
            set action[%%b]=%lastOpt%
            goto endOption
         )
      )
   )
   :endOption
   shift
if "%~1" neq "" goto nextOption

rem Select option
set /A opt=1, newOpt=1, key=0
CursorSize 0
:setFocus
   CursorPos !position[%opt%]!
   ColorShow %focusAttrib% option[%opt%]
   if %key% gtr 0 goto optSelected
   :nextKey
      GetKey
      set key=%errorlevel%
      if %key% equ %EnterKey% goto optSelected
      if %key% geq %LowcaseA% set /A key-=32
      if defined action[%key%] (
         if %key% lss 0 (
            call :!action[%key%]!
         ) else (
            set newOpt=!action[%key%]!
         )
      )
   if %newOpt% equ %opt% goto nextKey
   CursorPos !position[%opt%]!
   ColorShow %attrib% option[%opt%]
   set opt=%newOpt%
goto setFocus
:optSelected
CursorSize /L
echo/
exit /B %opt%

:RightArrow
if %opt% lss %lastOpt% set /A newOpt=opt+1
exit /B

:LeftArrow
if %opt% gtr 1 set /A newOpt=opt-1
exit /B

:Ctrl_RightArrow
if %opt% lss %lastOpt% set newOpt=%lastOpt%
exit /B

:Ctrl_LeftArrow
if %opt% gtr 1 set newOpt=1
exit /B

A couple examples of previous subroutine:

Code: Select all

rem The classical one
call :Select "Are you sure?" Yes No
if %errorlevel% equ 1 goto execute

rem A more complete example
call :Select /%Blue%%BWhite% "Select the desired day:" /%Red%%Yellow% Monday Tuesday Wednesday tHrusday Friday
set desiredDay=%errorlevel%


Antonio
Last edited by Aacini on 08 Jan 2013 02:56, edited 2 times in total.

Fawers
Posts: 187
Joined: 08 Apr 2012 17:11
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#9 Post by Fawers » 09 Jul 2012 00:14

StrLen.exe is going to help me a lot. Thank you very much, Antonio.

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Advanced Batch features via auxiliary .exe programs

#10 Post by Aacini » 13 Jul 2012 23:42

The Batch program below is a simple, but funny example of text animation.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem Example of text animation

echo Please wait . . .
cls
echo/
set file=
for /F "delims=" %%a in ('dir /b /o:d *.txt') do set file=%%a
if not defined file for /F "delims=" %%a in ('dir /b /o:d *.bat') do set file=%%a
for /F "delims=" %%a in ('Show 32*60 13 10') do set fileContent=%%a
set i=0
for /F "usebackq delims=" %%a in ("%file%") do (
   set /A i+=1
   set "fileContent=!fileContent!!i!: %%a  "
)
StrLen fileContent
set fileLen=%errorlevel%

echo Contents of file "%file%":
CursorPos +9 +2
Show "["
CursorPos
set position1=%errorlevel%
Show 32*60 "]"

set i=0
rem                Waves                   Rotating                   Ping-pong                   Rotating                     Waves
for %%a in (
   "Show 219  32  32  32  32  32  32x5  47 196  92 124  32x5  219 62 32 32 32 32 32  32  32x5  92 124  47 196  32x5  219 178 177 176  32  32"
   "Show 219 219  32  32  32  32  32x5 196  47 124  92  32x5  178 32 62 32 32 32 32  32  32x5 124  92 196  47  32x5  178 177 176  32  32  32"
   "Show 178 219 219  32  32  32  32x5  92 124  47 196  32x5  177 32 32 62 32 32 32 176  32x5  47 196  92 124  32x5  177 176  32  32  32  32"
   "Show 177 178 219 219  32  32  32x5 124  92 196  47  32x5  176 32 32 32 62 32 32 177  32x5 196  47 124  92  32x5  176  32  32  32  32  32"
   "Show 176 177 178 219 219  32  32x5  47 196 92  124  32x5   32 32 32 32 32 62 32 178  32x5  92 124  47 196  32x5   32  32  32  32  32  32"
   "Show  32 176 177 178 219 219  32x5 196  47 124  92  32x5   32 32 32 32 32 32 62 219  32x5 124  92 196  47  32x5   32  32  32  32  32  32"
   "Show  32  32 176 177 178 219  32x5  92 124  47 196  32x5   32 32 32 32 32 32 60 219  32x5  47 196  92 124  32x5   32  32  32  32  32 219"
   "Show  32  32  32 176 177 178  32x5 124  92 196  47  32x5   32 32 32 32 32 60 32 178  32x5 196  47 124  92  32x5   32  32  32  32 219 219"
   "Show  32  32  32  32 176 177  32x5  47 196 92  124  32x5  176 32 32 32 60 32 32 177  32x5  92 124  47 196  32x5   32  32  32 219 219 178"
   "Show  32  32  32  32  32 176  32x5 196  47 124  92  32x5  177 32 32 60 32 32 32 176  32x5 124  92 196  47  32x5   32  32 219 219 178 177"
   "Show  32  32  32  32  32  32  32x5  92 124  47 196  32x5  178 32 60 32 32 32 32  32  32x5  47 196  92 124  32x5   32 219 219 178 177 176"
   "Show  32  32  32  32  32  32  32x5 124  92 196  47  32x5  219 60 32 32 32 32 32  32  32x5 196  47 124  92  32x5  219 219 178 177 176  32"
   ) do (       
   set /A i+=1
   set Show[!i!]=%%~a
)


echo/
CursorPos +15 +4
CursorPos
set position2=%errorlevel%

for /F "delims=" %%a in ('Show 32*40 "Press Enter key to continue . . . " 13 10') do set "message=%%a"
StrLen message
set len=%errorlevel%

echo/
CursorPos +18 +5
Show "["
CursorPos
set position3=%errorlevel%
Show 32*40 "]"

CursorSize 0
set /A char1=-1, i2=0, char3=-1, i3=0
:loop
   set /A char1+=1
   CursorPos %position1%
   Show "!fileContent:~%char1%,60!"
   if %char1% equ %fileLen% set char1=-1

   set /A i2+=1
   if %i2% gtr 12 set i2=1
   CursorPos %position2%
   !Show[%i2%]!

   set /A i3=-(i3-1)
   if %i3% equ 0 (
      set /A char3+=1
      CursorPos %position3%
      Show "!message:~%char3%,40!"
      if %char3% equ %len% set char3=-1
   )

   ping localhost -n 1 >nul
   GetKey /N
if %errorlevel% neq 13 goto loop

CursorSize /L
CursorPos 0 18


I added an index of these auxiliary programs in the first post of this topic; I suggest you to take a look at it.

Antonio

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Advanced Batch features via auxiliary .exe programs

#11 Post by Squashman » 30 Dec 2013 10:37

I was hoping we could get some of this type of stuff integrated into the main web page. I know someone came up a with a really cool pure batch solution to something a few months ago and I commented that it should go into the Function Library. I think it had something to do with passwords or something I can't recall.

berserker
Posts: 95
Joined: 18 Dec 2013 00:51

Re: Advanced Batch features via auxiliary .exe programs

#12 Post by berserker » 30 Dec 2013 12:47

talking about stretching the limits, how about using debug.exe to create a strlen function?

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Advanced Batch features via auxiliary .exe programs

#13 Post by Squashman » 30 Dec 2013 12:54

berserker wrote:talking about stretching the limits, how about using debug.exe to create a strlen function?

Try using that on a 64bit system.

berserker
Posts: 95
Joined: 18 Dec 2013 00:51

Re: Advanced Batch features via auxiliary .exe programs

#14 Post by berserker » 30 Dec 2013 18:18

Squashman wrote:
berserker wrote:talking about stretching the limits, how about using debug.exe to create a strlen function?

Try using that on a 64bit system.

use on a 32bit version then. I am sure with purists and experts who like to stretch their limits and come out with a solution.

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Advanced Batch features via auxiliary .exe programs

#15 Post by Squashman » 30 Dec 2013 18:23

berserker wrote:
Squashman wrote:
berserker wrote:talking about stretching the limits, how about using debug.exe to create a strlen function?

Try using that on a 64bit system.

use on a 32bit version then. I am sure with purists and experts who like to stretch their limits and come out with a solution.

If you search the forum you will see plenty of solutions that have used debug over the years and you will also notice that debug is not included in any version of Windows 7. Even the 32bit. We had this discussion on the forums already which is why this thread was started.

Post Reply