Page 1 of 1

Is there a RichView->BeginUpdate ?

Posted: Sat Aug 31, 2019 10:51 pm
by VicFan
A test demo I have been working on has very poor performance and I am wondering if it wasting a lot of time drawing on the screen prematurely while it is being calculated (as would be handled by a BeginUpdate() and EndUpdate() sequence), but I don't see that as being available for RichView. On my laptop, to draw 100 cycles, as this code shows, it takes 1 minute to draw the screen and display the buttons, completely unacceptable performance. Is there anything i can do to speed it up?

Second question, how do I go about freeing the memory used by the TButtons? If I execute the code within the ATTEMPT_TO_FREE_BUTTONS block, the code gets an invalid pointer exception error on the indicated line. If I don't try to free the memory then the buttons will still be on the screen after pressing the Clear button and then, on pressing the Add button again, all buttons will still be there.

Code: Select all

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#define ATTEMPT_TO_FREE_BUTTONS

#include "Unit1.h"
#include "RichView.hpp"
#include "RVStyle.hpp"
#include "RVTable.hpp"
#include "RVScroll.hpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "RichView"
#pragma link "RVScroll"
#pragma link "RVStyle"
#pragma link "RVEdit"
#pragma resource "*.dfm"
TcurrRichViewEdit *currRichViewEdit;
int docCount=0;
//---------------------------------------------------------------------------
__fastcall TcurrRichViewEdit::TcurrRichViewEdit(TComponent* Owner)
	: TForm(Owner)
{
}
void __fastcall TcurrRichViewEdit::OnButtonAClick(TObject *Sender) {
	TButton * btn = (TButton *) Sender;
	ShowMessage("Hi from Button " + btn->Name + ", Event A" );
    btn->Visible = false;
}
void __fastcall TcurrRichViewEdit::OnButtonBClick(TObject *Sender) {
	TButton * btn = (TButton *) Sender;
	ShowMessage("Hi from Button B");

}

int GetParaNoWithLeftMargin(TRVStyle* rvs, TRVStyleLength LeftIndent)
{
	TParaInfo* ParaStyle = new TParaInfo(NULL);
	ParaStyle ->Assign(rvs->ParaStyles->Items[0]);
	ParaStyle ->LeftIndent = LeftIndent;
	int r = rvs->FindParaStyle(ParaStyle);
	delete ParaStyle;
	return r;
}
//---------------------------------------------------------------------------
void __fastcall TcurrRichViewEdit::btnAddClick(TObject *Sender)
{
	TRVTableItemInfo *table;
	TRVTableCellData * Cell;
	TButton *btn;
	int paraNo;

	for (int j = 0; j < 100; j++) {

        rv->AddCheckpoint("Chk" + UnicodeString(++docCount), true);

		for (int i = 0; i < 5; i++) {

			table = new TRVTableItemInfo(1, 3 + i, rv->RVData);
			paraNo = GetParaNoWithLeftMargin(rv->Style, 40 * i);
			table->ParaNo = paraNo;

			Cell = table->Cells[0][0];
			Cell->Clear();
			Cell->AddNL("Hi from cell 1", 0, 0);
			table->SetCellTag(UnicodeString(i), 0, 0);

			Cell = table->Cells[0][2];
			Cell->Clear();
			Cell->AddNL("Hi from cell 3", 0, 0);

			Cell = table->Cells[0][i+2];
			Cell->Clear();
			Cell->AddNL("Hi from last cell. I am writing this from the last cell", 0, 0);

			rv->AddItem("Row_" + UnicodeString(j*5+i) , table);
			free(table);

			btn = new TButton((TComponent*) NULL);   // Note: keyword NEW used here
			btn->Name = "Btn" + UnicodeString(i);
			switch (i % 2) {
			case 0:
				btn->OnClick = OnButtonAClick;
				btn->Caption = "A button";
				btn->Name = "btnA" + UnicodeString(i);
				break;
			case 1:
				btn->OnClick = OnButtonBClick;
				btn->Caption = "B button";
				btn->Name = "btnB" + UnicodeString(i);
				break;
			}
			rv->AddControl("Btn_" + UnicodeString(j*5 + i), btn, paraNo, rvvaAbsMiddle);
			// free(btn);   // Can't free the button or removes the instance I just set up

			rv->FormatTail();
		}
	}

    rv->ScrollTo(0);

}
//---------------------------------------------------------------------------
void __fastcall TcurrRichViewEdit::btnClearClick(TObject *Sender)
{
	TButton *btn;
	TCustomRVItemInfo *item;

	#ifdef ATTEMPT_TO_FREE_BUTTONS
	for (int i = 0; i < rv->ControlCount; i++) {
		item = rv->GetItem(i);
		if (item->ItemText.SubString(1,4) == "Btn_") {
			free(item);
		}
	}
   #endif
	rv->ClearAll();     // Doesn't seem to clear the buttons
	rv->FormatAll();    // First chance exception at $75083442. Exception class EInvalidPointer with message 'Invalid pointer operation'. Process Project1.exe (23160)                     //
}
//---------------------------------------------------------------------------

Re: Is there a RichView->BeginUpdate ?

Posted: Sun Sep 01, 2019 7:27 am
by Sergey Tkachenko
Add*** methods do not redraw document (moreover, redrawing after calling Add***methods but before formatting might crash the application).
The obvious speed improvement is moving FormatTail() out of the cycle to the end of the method.

You cannot just free inserted controls while they are in a document. There are still references from TRichView, and the application crashes when TRichView tries to access them. You can only delete items containing these controls, using the methods: Clear, DeleteItems, DeleteParas.