私は長いプロセスの間、私のコンソールアプリケーションに何らかのアニメーションを表示したいと思います。Delphiを使用してコンソールアプリケーションにプログレスバーを表示する方法は?
私は既に研究を行っていますが、私が見つけた解決策は興味を起こさなかったし、私はそれらを理解することができなかった。
私のアプリケーションは、テキストファイルを読み込み、置換する単語を検索することによって、すべての行を1つずつトラバースします。
これはプログレスバーまたはループアニメーションです。
私は長いプロセスの間、私のコンソールアプリケーションに何らかのアニメーションを表示したいと思います。Delphiを使用してコンソールアプリケーションにプログレスバーを表示する方法は?
私は既に研究を行っていますが、私が見つけた解決策は興味を起こさなかったし、私はそれらを理解することができなかった。
私のアプリケーションは、テキストファイルを読み込み、置換する単語を検索することによって、すべての行を1つずつトラバースします。
これはプログレスバーまたはループアニメーションです。
メッセージを生成するサンプルは次のとおりです。Y(Z%)...のXをループ内で処理し、ループ内で何かを実行するのにかかる時間を表す遅延があります。明らかに、それは人為的な例ですが、1つの可能性を示しています。 (また明らかに、このようなTStringList.Count
などの意味のある値を持つメッセージループとYの上限値を置き換えることになる。)
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.
進捗インジケータ
のスナップショット長い、長い時間前。 1つは、VT100の緑色の文字を表示するチューブでメインフレームと通信するために使用されました。それ以来、コマンドラインインターフェイスを使用しているプログラムは、実際には(バーチャル)VT100のバックエンドと通信しています。コードASCIIに大きく基づいているため、画面上のどこに表示されたかを制御するには、これらの最低値が重要です。そのため、新しいタイプのラインは、テレタイプのライターで「キャリッジリターン」を行う#13
と、チェーンフィード用紙に1本のラインを送る#10
の2種類があります。 VT100は、次の受信文字を表示するように位置を変更することによって、同じことをシミュレートしました。
には、をコンソールウィンドウの画面に上書きするには、#13
と新しいデータを送信してください。たとえば、次のように
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;
とWriteLn;
(実際Write(#13#10);
である)、または#13
と全体のバーを上書きするのに十分な長さで始まる何か他のものとのいずれかで終わります。
このコンソールアプリケーションを試してみてください。
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.
これが行うようなOSのコンソールアプリケーションでプログレスバーを表示する古い方法です。もちろん、より良い方法がたくさんありますが、うまくいくだけです。 デリーはCRTツールをサポートしていなかったので、画面をクリアするためにProcedure
を追加します。
進捗インジケータが単なる増加した整数の場合は、 'write'(' writeln'ではなく)とそれに続くキャリッジリターンを使用してコンソールに書き込みます。これにより、以前の値が上書きされます。 – MartynA
@ジェリードッジあなたが変更したい部分を説明したところで、アプリケーションは少し複雑です。 – Anderson
私は ' - \ |/'、プロセスが終了するまで画面上の同じ場所で繰り返します。 –