0

I am trying to stop screen flicker when it comes to my batch program that is used to display a text file on the screen. It has to update and the only way I have come up with is to loop the program and clear the screen.

This is my current code.

::Begin the refresh loop
::---------------------------------------------------------------
:Refresh


type "%ud%\ChatTerminal\Msg.txt

Sleep 1

cls


Goto Refresh
:Break Refresh
::---------------------------------------------------------------
::Refresh Loop Ends
::---------------------------------------------------------------

After some research I came to this post: How do I remove flickering from a batch file animation?

The issue is that I would not know where to start with the implementation.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Dominique
  • 9
  • 6

3 Answers3

2

The escape character for VT sequences can be defined using:

For /F %%e in ('echo prompt $E^|cmd')Do set "\E=%%e"

Depending on the format and contents of each .txt file, flicker free animation could be as simple as returning the cursor to screen home between each 'frame':

<nul set /p "=%\E%[1;1H"

Edit

Should the source file/s be of differing line lengths or line counts, then each line needs to be read in and the VT sequence %\E%[K prepended to clear the remainder of the line and %\E%[0J after each file to clear the remainder of the console screen from the cursor location.

An example, which creates files to animate: (Note: %\E%[E emits a line feed )

Anim.bat

@Echo off & CD /D "%~dp0"
 For /f %%e in ('Echo Prompt $E^|cmd') Do set "\E=%%e"
 <nul Set /P "=%\E%[?25l"
 Set /A "delay=4", "Files=0","FC=1"

 Setlocal EnableExtensions EnableDelayedExpansion

 For %%i in (5 6 7 8 9 10 11 12 13 14 15 14 13 12 11 10 9 8 7 6 5)Do (
  Set /A Files+=1
  Call :CreateCube %%i "infile!Files!.txt"
 )

 For /L %%i in ()Do (
  for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
  if !tDiff! lss 0 set /a tDiff+=24*60*60*100
  if !tDiff! geq !delay! (
   Set /A "FC=FC %% Files + 1"
   <nul Set /P "=%\E%[1;0H"
   If !FC! GTR 10 (If !Offset! GTR 1 Set /A "Offset-=1")Else Set "offset=!FC!"
   (For /f "Delims=" %%G in (infile!FC!.txt)Do <nul set /P "=%\E%[K%\E%[!offset!G%%G%\E%[E") > Con
   <nul Set /P "=%\E%[0J"
   set /a t1=t2
  )
 )

:CreateCube <size>
:# golfed script for outputting a shaded multi color cube
:# https://codegolf.stackexchange.com/a/224741/92319
@echo off&Cls&Set $=Set &CHCP 65001 > nul
If "%~1"=="" (Echo(%~n0 Integer Outfile.ext&Exit /B)
If "%~2"=="" (Echo(%~n0 Integer Outfile.ext&Exit /B)
(<Nul Set /p "=%\E%7")>"%~2"
%$%/A x=%1,h=x*2,z=0
%$%F=For /L %%a in (1 1 &%$%P=^<nul set/p &%$%C= If %%y LEQ %1 
((%f:a=y%!h!)Do (%$%/a w=x-z
%F%!w!)Do %P%"=%\E%7 "
%F%!z!)Do%C%(%P%"=%\E%[38;2;0;120;%%a0m_|")Else %P%"=%\E%[4m%\E%[38;2;120;0;%%a0m\\%\E%[0m"
%F%%1)Do%C%(%P%"=%\E%[38;2;120;0;%%a0m▲▼")Else %P%"=%\E%[38;2;0;120;%%a0m_\"
%C:EQ=SS%(%$%/A z+=1)Else%C:If=If not%%$%/A z-=1)&Echo(%\E%[0m))>"%~2"

Note: the time elapsed operation used for framerate originates from Dave Benhams snake.bat

Implementation of framerate control in a repeating for /l infinate loop is strongly recommended to facilitate a smooth animation - failure to do so will result in the animation appearing jagged / choppy as it occurs at a pace the eye cant follow

T3RR0R
  • 2,747
  • 3
  • 10
  • 25
0

T3RR0R's solution overwrites existing lines without deleting the rest of the old line. So when the new line is shorter, the rest of the old line keeps showing.

That could be solved by writing the file line by line, deleting the rest of the line. Sadly that slows things down and thus re-introduces the flicker (at least for files with more than one line).

As an alternative, only write the file, if it has changed. It still flickers, but now just when the file is updated. After displaying the file, unset the archive attribute. Whenever Windows writes to the file, it sets the attribute again, which we use to determine if the file has changed.

@echo off
set "file=%ud%\ChatTerminal\Msg.txt"
:loop
attrib "%file%"|findstr /b "A" >nul && (
  cls
  type "%file%"
  attrib "%file%" -a
)
timeout 1 >nul
goto :loop

Bonus: this doesn't use Escape codes, so it runs on every Windows version (possibly there are a few deprecated Windows versions that didn't have timeout by default, but it can be replaced with ping when needed)

Stephan
  • 53,940
  • 10
  • 58
  • 91
0

Seems like all you are trying to do is TAIL a file and print the those new lines to the screen. You can use this method to accomplish that.

@echo off

call :Read <"file.txt"

GOTO :EOF

:Read
set "line="
set /p "line="
if defined line (
  echo %line%
)
goto :Read
Squashman
  • 13,649
  • 5
  • 27
  • 36