问题
TMemo cannot handle Unix enters (LF) correctly. Two lines separated with a LF are shown and treated as one line. I want to handle all possible text formating (Mac, Win, Unix).
Obviously I could check the text and replace the LF with CRLF every time I:
- load text form file
- paste text
- use the Add() function
- use the Insert() function
- use the Appen() function
- change the content via Text property
But this won't be an elegant solution.
Lazarus solved this problem with the Lines.TextLineBreakStyle property. There is anything similar in Delphi XE?
回答1:
You're asking specifically about line-ending sequences, but we can easily broaden the discussion to controlling the contents of an edit box in general.
In 2001, Peter Below wrote an outline of all the things you need to handle for an edit control that accepts only numerals. The techniques are still applicable today, at least for Windows development. Here's a summary:
- Override
KeyPress
to filter out unwanted keystrokes. (In your case, you don't need this because there aren't any keys you want to exclude.) - Handle the
wm_Paste
message to account for text pasted from the clipboard. - Handle the
wm_SetText
message to account for text being set in most other conventional ways. (This takes care of most of your list:LoadFromFile
,Add
,Append
,Insert
,Text := ...
.) - Handle the
em_ReplaceSel
message to account for selected text being overwritten.
In Below's write-up, he simply rejects any non-conforming input. That's probably not what you want, though. Instead, you'll want to normalize the input so that it uses uniform line-ending sequences. Rather than just swallow the text-changing messages listed above, you'll want to massage the input and then forward it to the normal handler.
For controlling line endings, Delphi already provides a function that does the kind of massaging you want: AdjustLineBreaks. You can pick whether you want Unix- or Windows-style line endings. (Note that not even Macintosh uses Mac-style line endings anymore.) You probably want tlbsCRLF
because that's the style the Windows edit control knows how to display; as you've noted, it doesn't display line breaks if there aren't any carriage returns.
For wm_SetText
and em_ReplaceSel
, the change is easy. Here's a sketch:
procedure TLineNormalizingMemo.WMSetText(var Message: TWMSetText);
var
s: string;
begin
s := Message.Text;
s := AdjustLineBreaks(s);
Message.Text := PChar(s);
inherited;
end;
It's not quite so obvious for wm_Paste
because you're not given the new text, and you're not supposed to change the text that's currently on the clipboard. Instead, you can opt not to call inherited
, handling the effects of pasting yourself. Something like this:
procedure TLineNormalizingMemo.WMPaste(var Message: TWMPaste);
var
s: string;
begin
if Clipboard.HasFormat(cf_Text) then begin
s := Clipboard.AsText;
s := AdjustLineBreaks(s);
SelText := s;
end;
end;
Since assigning SelText
goes through the em_ReplaceSel
message, you might not even need to call AdjustLineBreaks
there.
回答2:
Just set the Lines.LineBreak
property to LF
:
memo1.lines.LineBreak := #10;
The default is #13#10
in Windows.
来源:https://stackoverflow.com/questions/26405800/tmemo-cannot-handle-unix-text-lf-as-line-ending-correctly