3

I'm using CodeGear C++ Builder 2009 and have problems with the TMemo component. It's too slow. I use it to display ASCII text from the COM serial port. I need to display every single symbol when it comes from the COM Serial port. The problem is, if there is a lot of text from the COM serial port, older text on TMemo starts to flicker and all the more text is on the component, the worse it gets. When TMemo contains 1000 lines of text, refresh delay is enormous!

I set doubleBuffered property to true, but this not helping a all. How they make refresh time to be minimum in applications like SecureCRT? New text is added smoothly and there is no flickering. Which component can produce such result?

manlio
  • 18,345
  • 14
  • 76
  • 126
Hitman_99
  • 2,252
  • 2
  • 19
  • 21

2 Answers2

1

Rather than displaying the characters in real-time to the TMemo as they arrive, try saving them to an in-memory buffer first, and then have a short timer copy the buffer into the TMemory periodically, and make use of the Lines->BeginUpdate() and Lines->EndUpdate() methods when adding new text. Also, 1000 lines is a lot, you may have to start removing older lines as newer lines are added after awhile. I usually limit my TMemo controls to a few hundred lines at a time.

Update: try something like this:

TMemoryStream *Buffer;

// serial port callback
void BytesReceived(void *Data, int Length)
{
    Buffer->Position = Buffer->Size;
    Buffer->WriteBuffer(Data, Length);
}

__fastcall TForm1::TForm1(TComponent *Owner)
    : TForm(Owner)
{
    Buffer = new TMemoryStream;
}

__fastcall TForm1::~TForm1()
{
    delete Buffer;
}

void __fastcall TForm1::TimerElapsed(TObject *Sender)
{
    if (Buffer->Size > 0)
    {
        Memo1->Lines->BeginUpdate();
        Memo1->SelStart = Memo1->GetTextLen();
        Memo1->SelLength = 0;
        Memo1->SelText = AnsiString((char*)Buffer->Memory, Buffer->Size);
        Memo1->SelStart = Memo1->GetTextLen();
        Memo1->Perform(EM_SCROLLCARET, 0, 0);
        Memo1->Lines->EndUpdate();
        Buffer->Clear();
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I implemented BeginUpdate() and EndUpdate(), they solved some issues. Buffering text before putting it in memo would be perfect, but I can't do this, because I need to see every byte right away. Example: after sending firmware to the device connected to SerialCom port, there's some sort of progress, indicated by dots (.), so when I'm buffering input I can't see this progress. I'm planning to work on this project later this year, so if I'll come up with a solution I'll post it here. – Hitman_99 Sep 23 '11 at 12:38
  • That's why I said to use a short timer to flush the buffer periodically, say 100-250ms. You will still get near real-time UI updates, but the insertions into the Memo can be more efficient - fewer larger inserts instead of more smaller inserts. Also, for the actual inserts, the most efficient way to insert new text is to Set the SelStart property to the end of the Memo and then set the SelText property, instead of using Add() or the Text property. – Remy Lebeau Sep 23 '11 at 14:59
  • Using your proposed technique, is it possible to keep scrollbar to the bottom of the memo window? Because new entries is not visible, you need to drag scrollbar to the end of the window. – Hitman_99 Sep 30 '11 at 15:00
  • After inserting new text, put the caret at the end of the text again (by setting the `SelStart` property) and send an `EM_SCROLLCARET` message to the Memo. I have updated the example. – Remy Lebeau Sep 30 '11 at 22:54
  • Thanx. But Memo->Perform(EM_SCROLLCARET, 0, 0); do nothing, if it's called before Memo1->Lines->EndUpdate(); It does not scroll the text. But this works perfect, when called after Memo1->Lines->EndUpdate(); – Hitman_99 Oct 03 '11 at 07:19
0

as for window devices, . . best way is uses thread event instead of timer event, . . place serial wait event inside thread->execute(), (this is a do while loop, . .)

serial wait event will do nothing until something received,.. soon it received into a *buffer, check length of buffer/string, . .

then place in memo as

memo->text=buffer;
or 
memo->lines-add(buffer);
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335