Lazarus
Installation => Windows (32/64) => Topic started by: tech-pro on November 10, 2007, 09:57:30 am
-
I am using a TMemo to display text that is received from a serial port. It appears that when I add newly received text, like this:
Memo.Text := Memo.Text + newtext;
a newline gets added to the end of the text, so the cursor is on the next line and every chunk of text received is on a new line.
Any ideas for a solution?
-
I don't know how other Delphi versions behave, but D3 Pro (Win9x) does not add the newline as opposed to Lazarus.
If this Lazarus behaviour also differs from newer Delphi versions, it may be considered a bug and reported IMHO.
Bart
-
Try
memo1.lines.text := trim(memo1.lines.text) + 'text';
-
I just checked in Delphi 6 and it does not add the new line.
I tried your suggestion, Antonio, and although it does partially solve the problem (except that it removes any trailing spaces, but that could be fixed) the trouble is that the new line is added when the text is written to the control, so the cursor is positioned on the next line. This is a problem because I want it to be like a real terminal window where you can type text as well as have received text printed up.
The original Delphi code didn't use a TMemo. It derived from TCustomEdit and made it multi-line with word-wrap and a scroll bar. Unfortunately the method used to achieve this - by recreating the window after adding some styles - doesn't seem to work with the LCL and despite much studying of the LCL source code I haven't figured out how to do this.
-
I think the bug already has been reported.
-
Should the application run on Windows only?
-
I think the bug already has been reported.
Yeah, it's in bugreport #9653 (http://www.freepascal.org/mantis/view.php?id=9653).
It seems that TStrings.SetTextStr adds a LineEnding after the text becaus it uses TSrings.Add, which uses TSrings.Insert, which in fact adds the LineEnding to the string.
Bart
-
It's going to run on Windows though I wanted to make as little of it Windows-specific as possible.
I checked Delphi adding the text to TStrings.Text and it appeared to add a line ending, the same as Lazarus. Only the memo does it differently.
I have managed to work around it after a fashion using something similar to Antonio's first suggestion.
-
You might want to consider using SelText for this purpose? It puts the text at the position of the cursor (which might be a problem if the user changes that).
Bart
-
Yes, I will try to do something like that. As this has been reported as a bug, it will hopefully eventually be fixed.
-
Further to this, I've managed to work around the problem so the text can be added a character at a time, but has anyone any suggestions as to how I can avoid flicker when the memo is updated? I've tried disabling it before the update and enabling it afterwards, but that hasn't made any difference.
-
TMemo.Lines.Beginupdate / Endupdate?
Make your form doublebuffered?
(I only know how to do that in win32) Call windows to lock the the painting of the form entirely?
Just curious: how do you add one character at a time, without using the text property I assume (since this will add the LineEnding).
Does anyone know how to remove in code the last LineEmding from the memo?
Bart
-
I'll investigate if those possibilities exist in LCL. Thanks.
At the moment, there's no alternative than to add characters using the Text property. Dealing with the line end is very kludgey. You have to remove CR and LF characters from the end of the string, unless you actually added them yourself and therefore want them.
-
Does anyone know how to remove in code the last LineEnding from the memo?
Use Trim;
function Trim(const S: widestring): widestring;
-
Unfortunately sometimes you want new lines to appear in the memo text, also Trim will remove spaces (remember, you are adding text character by character.)
You have to store what you added and manually remove line endings only if they were not added by you.
-
Does anyone know how to remove in code the last LineEnding from the memo?
Use Trim;
function Trim(const S: widestring): widestring;
I'm sorry I did not make myself clear.
What I meant was: how do I remove in code the LineEning from the memo that was added by setting the TMemo text property in code (Memo.Text := SomeText). So that it is removed from the memo itself.
If we can do this, then we can modify SetTextStr() to prevent TMemo from adding a LineEnding if we set the textproperty of a TMemo control, thus fixing the bug.
Bart
-
The last lineend is the result of the used TStrings.text. It contains lines, when the Text is "askes" all lines are concatinated whith a terminating LineEnding
-
The last lineend is the result of the used TStrings.text. It contains lines, when the Text is "askes" all lines are concatinated whith a terminating LineEnding
Yes, but that is undesired when setting text in a TMemo (and not compatible with Delphi behaviour).
The most logical place to resolve this IMHO is the SetTextStr procedure. This would involve removing the last LineEnding after setting the text.
If that can be done, the bug is fixed.
Bart
-
You need to be sure that you don't remove the line ending if the string set by the user ended in one. This has been one of the difficulties in producing a workaround.
By the way I still haven't managed to stop the flicker when the memo gets updated. Tried double buffering it, and used BeginUpdateBounds/EndUpdateBounds (admittedly without being able to figure out what they do) to no avail.
-
You need to be sure that you don't remove the line ending if the string set by the user ended in one. This has been one of the difficulties in producing a workaround.
That should not be so hard? If user sets text, we know what text will be, so we know if it ends in LineEnding. If it does not, then we remove last LineEnding after we set text.
It can be done. Delphi does it, so why can't we?
Bart
-
I wasn't suggesting it can't be done, I just wanted to make the point that sometimes a line ending will be the last thing in the text.
A fix for this won't solve the problem of the memo flickering when it is updated. It seems to me that this is happening because it has to be updated in two stages. First the new text is set, and the control displays it starting with the first line. Then I have to set the caret position to the end, so that the last character entered is in view. If the length of the text is greater than can fit in the visible area, it scrolls, and this causes the flickering.
LCL components don't seem to have the BeginUpdate / EndUpdate methods suggested earlier in this thread. There is BeginUpdateBounds and EndUpdateBounds but I don't know what they do, and when I tried them anyway they didn't deem to do anything.