我有一个简单的“畜生”大文本文件(20 big )。我想在TRichEdit上展示一下。问题是它需要6秒才能显示出来。为了避免这个糟糕的UX设计,我想在应用程序的底部放一个程序栏。
我的问题是如何获得TRichEdit展示的进展?使用TRichEdit::LoadFromStream方法,它的速度从0到100% (小于1秒),但是在应用程序等待6秒钟之后,在第一次显示中。
我用FileStreamProgress继承TFileStream创建了这个类。我覆盖了TFileStream::Read()
int __fastcall FileStreamProgress::Read(void *Buffer, int Count)
{
__int64 previousPosition = this->Position;
int ret = TFileStream::Read(Buffer, Count);
if (this->Position == 0 || this->Position == this->Size || (previousPosition/128000) != (this->Position/128000)) {
ProgressCallBack(ProgressCallBackParam1, this->Position, this->Size);
}
return ret;
}
static void FileStreamProgress::ProgressCallBack(void*thiz, int i, int max)
{
TProgressBar* ProgressBar = (TProgressBar*)thiz;
if (ProgressBar)
{
if (max > 0)
{
ProgressBar->Position = int(i * 100 / max);
}
if (Application)
{
Sleep(1);
Application->ProcessMessages();
}
}
} 我就是这样测试的:
void MyApp::CreatePage(AnsiString filename)
{
ProgressBar->Visible = true;
FileStreamProgress::ProgressCallBackParam1 = (void*)this->ProgressBar;
TFileStream * stream = new FileStreamProgress(filename.c_str(), fmOpenRead);
TPageMemo* Page = new TPageMemo(this);
Page->Parent = PControl;
Page->PageControl = PControl;
MessageDlg("111",mtError,TMsgDlgButtons()<<mbOK,0);
Page->Texte->Lines->LoadFromStream(stream);
MessageDlg("222",mtError,TMsgDlgButtons()<<mbOK,0);
PControl->ActivePage = Page;
}在两个消息对话框"111“和"222”之间有7个附庸。我的进度条等待6秒100% (在展示期间)
发布于 2020-02-06 07:51:14
我试图深入研究win32 API的SendMessage,并在没有预期结果的情况下进行处理。
最后,我昨天使用了一个TMemo,因为它是一个粗俗的文本。它非常快(即时打开),但是缺少一些函数,比如FindTextW()。我重写了它。谢谢
http://docwiki.embarcadero.com/RADStudio/Rio/en/Memo_and_Rich_Edit_Controls
发布于 2020-02-06 15:42:43
出于好奇,我对TRichEdit进行了测试,并想出了如下结论:
//---------------------------------------------------------------------------
void load_text(TRichEdit *re,AnsiString filename,TProgressBar *pb)
{
// variables
int hnd,adr,siz,len,i;
const int _buf=128*1024; // buffer size
AnsiString s,s0;
char buf[_buf+1];
// open file and detect size
hnd=FileOpen(filename,fmOpenRead); if (hnd<0) return;
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
// prepare progress bar
pb->Position=0;
pb->Max=siz;
pb->Visible=true;
// process txt file by chunks
for (s0="",adr=0;adr<siz;)
{
// update progress bar and GUI
pb->Position=adr;
Application->ProcessMessages();
// load chunk
len=FileRead(hnd,buf,_buf);
adr+=len; buf[len]=0;
// handle cutted lines by chunk size
s=s0; s0="";
// ignore last 2 lines for chunks (except last chunk)
if (len==_buf)
{
// skip last line
for (i=len-1;i>=0;i--)
if ((buf[i]==13)||(buf[i]==10))
{
i--;
if (i>=0)
if (buf[i]!=buf[i+1]) // different eol code to ignore empty line
if ((buf[i]==13)||(buf[i]==10)) // eol code
i--;
break;
}
// skip another line to avoid inserting empty line if eol is cutted
for (;i>=0;i--)
if ((buf[i]==13)||(buf[i]==10))
{
s0+=buf+i+1; // copy last 2 lines into s0
i--;
if (i>=0)
if (buf[i]!=buf[i+1]) // different eol code to ignore empty line
if ((buf[i]==13)||(buf[i]==10)) // eol code
i--;
i++; if (i<0) i=0; buf[i]=0; // end of string
break;
}
}
// last chunk ignore last eol
else{
// skip last line
i=len-1;
if ((buf[i]==13)||(buf[i]==10)) // eol code
{
i--;
if (buf[i]!=buf[i+1]) // different eol code to ignore empty line
if ((buf[i]==13)||(buf[i]==10)) // eol code
i--;
i++; if (i<0) i=0; buf[i]=0; // end of string
}
}
// add actual chunk
s+=buf;
re->Lines->Add(s);
}
// tidy up
pb->Visible=false;
FileClose(hnd); hnd=-1;
}
//---------------------------------------------------------------------------看起来,它不需要您描述的结束暂停,但是,这可能与我正在使用的、BDS2006、Turbo、C++、的版本有关。当在~23 MByte STL文件上进行测试时,加载时间为~10秒(TMemo花费了上帝的两倍,知道为什么).
保存的文件(而PlainText=true)与加载的文件相同,因此代码应该是正确的。
这里是预览的动画GIF:

当像这样使用时:
void __fastcall TForm1::FormActivate(TObject *Sender)
{
//tbeg();
load_text(re_txt,"in.txt",pb_progress);
//tend();
//Caption=tstr();
re_txt->Lines->SaveToFile("out.txt");
}其中pb_progress是TProgressBar,re_txt是TRichEdit。
你可以看到不需要回调..。
PS.如果您想像我一样度量时间(注释行),tbeg/tend/tstr函数的实现如下:
https://stackoverflow.com/questions/60071903
复制相似问题