我想在漫长的过程中在我的控制台应用程序中显示某种动画,并且不知道如何执行此操作。如何使用Delphi在控制台应用程序中显示进度条?
我已经做了一项研究,但是我找到的解决方案没有引起我的兴趣,或者我不乐意了解它们。
我的应用程序加载一个文本文件,并通过搜索要替换的单词来遍历所有行。
它可能是一个进度条或任何循环动画。
我想在漫长的过程中在我的控制台应用程序中显示某种动画,并且不知道如何执行此操作。如何使用Delphi在控制台应用程序中显示进度条?
我已经做了一项研究,但是我找到的解决方案没有引起我的兴趣,或者我不乐意了解它们。
我的应用程序加载一个文本文件,并通过搜索要替换的单词来遍历所有行。
它可能是一个进度条或任何循环动画。
下面是一个示例,它将生成消息在循环中处理Y(Z%)...的X,延迟时间表示在循环中执行某些操作的时间。显然,这是一个人为的例子,但它表明了一种可能性。 (也很明显,你将取代值的循环和Y具有有意义的值的消息中的上限值,例如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.
快照进度指示器的
很久很久以前;一个用于与显示绿色字母的管的大型机通信,类型为VT100。自那时以来发生了很大变化,除了使用命令行界面的程序实际上仍然与(虚拟)VT100的后端通信。严重依赖于ASCII代码,这32个最低值对于控制显示在屏幕上的哪个位置很重要。这就是为什么一些新线路在某些环境下仍然编码为#13
,这将在远程型作家上做'回车',而#10
将为链式馈送纸张提供一条线路。通过修改位置来显示下一个接收到的字符,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
@Jerry Dodge该应用程序稍微复杂一点,只是解释了你想改变的部分。 – Anderson
我更喜欢字符“ - \ |”的顺序/',在屏幕上的相同位置重复,直到过程完成。 –