简体   繁体   中英

How to load from memory stream to firemonkey (FMX) memo component in C++ Builder Berlin?

I used to use below code to load plenty of text to VCL Memo.

LogMemo->Lines->BeginUpdate();
LogMemo->SelStart = LogMemo->GetTextLen();
LogMemo->SelLength = 0;

LogMemo->SelText = AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->SelStart = LogMemo->GetTextLen();
LogMemo->Perform(EM_SCROLLCARET, 0, 0);
LogMemo->Lines->EndUpdate();

But in FMX Memo component, I can't use "LogMemo->SelText = AnsiString(strFromMemStream)" anymore. And I also can't use "GetTextLen" method to set selection start.

I tried to modify the code in below but it still didn't work. It always overwrite original content and can't append new text.

LogMemo->Lines->BeginUpdate();
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemo->SelLength = 0;

LogMemo->Text = AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemoBufPtr->Clear();
LogMemo->Lines->EndUpdate();

Is there any one know how to do it in FMX Memo component or just to display plenty of text smoothly?

Thanks!

Use the SetText function or Lines property.

In both cases I think you will have to convert the ASCII text to Unicode first.

Solution 1 - Based to the second source code provided, here is a solution to append a text in the TMemo object in FMX/FireMonkey Library.

Step 1 - Instead of trying to place the cursor and select the end of the text.

Before:

LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemo->SelLength = 0;

Select all the text and store it in a temporary string.

After:

System::UnicodeString suTemp;

LogMemo->Lines->BeginUpdate();
LogMemo->GoToTextEnd();
LogMemo->SelStart = 0;
LogMemo->SelLength = LogMemo->Text.Length();
suTemp = LogMemo->SelText;

Step 2 - Then append the new text to the temporary string and update the Memo

suTemp += AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->Text = suTemp;
LogMemo->GoToTextEnd();
LogMemo->SelStart = LogMemo->Text.Length();
LogMemoBufPtr->Clear();
LogMemo->Lines->EndUpdate();

Solution 2 - Simple and faster solution when add the text at the end.

Store the current text into a temporary string and add the new text then update the memo.

System::UnicodeString suTemp;

LogMemo->Lines->BeginUpdate();
suTemp = LogMemo->Text;

suTemp += AnsiString((char *)LogMemoBufPtr->Memory, LogMemoBufPtr->Size);
LogMemo->Text = suTemp;
LogMemo->GoToTextEnd();
LogMemoBufPtr->Clear();
LogMemo->Lines->EndUpdate();

TMemo in FireMonkey has a GoToTextEnd() method:

Moves the cursor to the end of the text in the memo control.

You can't use AnsiString in mobile platforms (without a compiler patch ), nor should you anyway since TMemo holds Unicode text (same as VCL's TMemo in Delphi 2009 and later). If your TMemoryStream contains 8bit characters, you need to convert them to Unicode, such as with TEncoding , before appending them to the TMemo . The TEncoding::GetString() methods take a TBytes as input, so you could use TBytesStream instead of TMemoryStream . TBytesStream wraps a TBytes and has a public Bytes property.

Try something like this:

LogMemo->Lines->BeginUpdate();
try
{
    LogMemo->GoToTextEnd();
    LogMemo->SelLength = 0;
    LogMemo->SelText = TEncoding::Default->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
    /* or:
    TEncoding *enc = TEncoding::GetEncoding(L"desired charset here");
    try {
        LogMemo->SelText = enc->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
    }
    __finally {
        delete enc;
    }
    */
    LogMemo->GoToTextEnd();
    LogMemo->SelLength = 0;
    // not sure if this is the best replacement for EM_SCROLLCARET...
    LogMemo->VScrollBar->Value = LogMemo->VScrollBar->Max;
}
__finally {
    LogMemo->Lines->EndUpdate();
}

Update : I didn't realize that SelText is read-only in FireMonkey, unlike in VCL. In that case, you have no choice but to append to the Text property, which is not as efficient, especially for large text.

LogMemo->Lines->BeginUpdate();
try
{
    LogMemo->Text = LogMemo->Text + TEncoding::Default->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
    /* or:
    TEncoding *enc = TEncoding::GetEncoding(L"desired charset here");
    try {
        LogMemo->Text = LogMemo->Text + enc->GetString(LogMemoBufPtr->Bytes, 0, LogMemoBufPtr->Size);
    }
    __finally {
        delete enc;
    }
    */
    LogMemo->GoToTextEnd();
    LogMemo->SelLength = 0;
    // not sure if this is the best replacement for EM_SCROLLCARET...
    LogMemo->VScrollBar->Value = LogMemo->VScrollBar->Max;
}
__finally {
    LogMemo->Lines->EndUpdate();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM