我想在漫长的过程中在我的控制台应用程序中显示某种动画,并且不知道如何做到这一点。
我已经做过研究,但我找到的解决方案并没有引起我的兴趣,或者我不乐意理解它们。
我的应用程序加载一个文本文件,并通过搜索要替换的单词逐个遍历所有行。
它可以是进度条或任何循环动画。
答案 0 :(得分:11)
这是一个示例,它将在循环中生成消息处理X的Y(Z%)... ,其延迟表示在循环中执行某些操作所花费的时间。显然,这是一个人为的例子,但它显示了一种可能性。 (显然,你会用一个有意义的值替换循环上限值和消息中的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.
进度指示器快照
答案 1 :(得分:4)
很久很久以前;一个曾经与大型机通信,管子显示绿色字母,类型为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
为前缀的其他内容结束,并且足以覆盖整个条形码。
答案 2 :(得分:2)
试试这个控制台应用程序:
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.
这是在dos等操作系统的控制台应用程序中显示进度条的老方法,当然有很多更好的方法,但它只是工作。
德里不支持CRT工具,所以我添加Procedure
用于清晰屏幕。