Home How to display a progress bar in a console application using Delphi?
Reply: 3

How to display a progress bar in a console application using Delphi?

Anderson
1#
Anderson Published in 2017-11-10 20:21:40Z

I would like to display some kind of animation in my console application during a long process and have no idea how to do this.

I already did a research but the solutions I found did not arouse my interest or I was not happy to understand them.

My application loads a text file and traverses all lines one by one by performing a search for words to be replaced.

It could be a progress bar or any loop animation.

Ken White
2#
Ken White Reply to 2017-11-11 04:58:54Z

Here's a sample that will produce the message Processing X of Y (Z%) ... in a loop, with a delay that would represent the time spent doing something in the loop. Obviously, it's a contrived example, but it shows one possibility. (Also obviously, you would replace the value for the upper limit of the loop and the Y in the message with a meaningful value, such as TStringList.Count.)

program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

var
  i: Integer;
  StopValue, Pct: Integer;

(* 
  #13 is a carriage return, which moves the cursor back to the
  left side of the console without adding a line feed (#10). It
  allows writing on the same line over the same content without
  moving to the next line. See the demo output.
*)
const
  StatusMsg = #13'Processing %d of %d (%d%%) ...';

begin
  StopValue := 150;     // Replace with your upper limit, e.g. StringList.Count
  for i := 1 to StopValue do
  begin
    Pct := Trunc((i * 1.0 / StopValue) * 100);
    Write(Format(StatusMsg, [i, StopValue, Pct]));
    (****************************************************************
      Note: The call to Sleep here is only to introduce an artificial
      delay in the loop in order to allow the progress to be seen. 
      Otherwise, the empty loop runs so fast that it's not clear when
      the progress increments are shown.

      Clearly, you would replace the call to Sleep with your code to
      actually do some work, such as processing each line of the text
      file.

      Explained in detail for clarity, as some commenters have indicated
      they're not capable of understanding why a call to Sleep is used
      here, so adding this unnecessarily large comment is needed for them.
    ****************************************************************)
    Sleep(250);
  end;
  Write(#13'Processing complete. Press Enter to quit.');
  ReadLn;
end.

Snapshot of progress indicator

Stijn Sanders
3#
Stijn Sanders Reply to 2017-11-10 20:44:23Z

A long, long time ago; one used to commune with the mainframe with a tube showing greenish letters, of the type VT100. Much has changed since then, except programs using a command line interface actually still commune with the back-end of a (virtual) VT100. Being heavily based on the ASCII codes, these 32 lowest values would be important to control which was shown where on the screen. That's why a new line is still encoded in some environments as a #13 which would do a 'carriage return' on a tele-type-writer, and a #10 which would feed the chain-feed-paper a single line. The VT100 simulated the same by modifying the position to display the next received character.

So to overwrite what's on screen in a console window, just send #13 and the new data. For example:

procedure ShowProgress(Position,Max:integer);
var
  i,j:integer;
const
  BarWidth=28; //must be less than 79
begin
  Write(#13'[');
  j:=Position*BarWidth div Max;
  for i:=1 to BarWidth do
    if i<=j then Write('#') else Write('-');
  Write(']');
end;

And end with either WriteLn; (which is actually Write(#13#10);) or with something else prefixed with #13 and long enough to overwrite the entire bar.

Aqil
4#
Aqil Reply to 2017-11-10 21:12:25Z

Try this console application:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, Windows;


procedure ClearScreen;
var
  stdout: THandle;
  csbi: TConsoleScreenBufferInfo;
  ConsoleSize: DWORD;
  NumWritten: DWORD;
  Origin: TCoord;
begin
  stdout := GetStdHandle(STD_OUTPUT_HANDLE);
  Win32Check(stdout<>INVALID_HANDLE_VALUE);
  Win32Check(GetConsoleScreenBufferInfo(stdout, csbi));
  ConsoleSize := csbi.dwSize.X * csbi.dwSize.Y;
  Origin.X := 0;
  Origin.Y := 0;
  Win32Check(FillConsoleOutputCharacter(stdout, ' ', ConsoleSize, Origin,
    NumWritten));
  Win32Check(FillConsoleOutputAttribute(stdout, csbi.wAttributes, ConsoleSize, Origin,
    NumWritten));
  Win32Check(SetConsoleCursorPosition(stdout, Origin));
end;

var
  iFileLineCount : Integer;
  iCounter1,iCounter2 : Integer;
  iPercent : Integer;
begin


  try
    iFileLineCount := 12000;
    for iCounter1 := 1 to iFileLineCount do
      begin

        //do your application thing like reading file
        ClearScreen;
        iPercent :=  iCounter1 * 100 div iFileLineCount;
        for iCounter2 := 1 to iPercent do
          write('|');
        write(IntToStr(iPercent) + '%');
      end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;



end.

This is old way to show a progress bar in console application for OS like dos, of course there is a lot of better ways, but it just working. Delhi did not support CRT tools , so i add a Procedure for clear screen.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.533968 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO