delphiformattingtrichedit

How do I insert new, unformatted, lines at the top of a TRichEdit


I am using TRichEdit to hold the body of an emailing client. I've given the user simple formatting capabilities (bold, italic, underline, left, centre and right paragraph alignment and bullets. This works well to email formatted text as html using Indy following Remy's code here.

I extract the TRichEdit text as html using

function GetHTML(RichEdit:TRichEdit): string;
var
    htmlstrings : Tstringlist;
    JvRichEditToHtml1  :TJvRichEditToHtml;
begin
 htmlstrings := Tstringlist.create;
 JvRichEditToHtml1 := TJvRichEditToHtml.create(nil);
 try
   JvRichEditToHtml1.ConvertToHtmlStrings(RichEdit,htmlstrings);
   result := htmlstrings.Text;
 finally
   htmlstrings.free ;
   JvRichEditToHtml1.free;
 end;
end;

Just before I send the email I use code to insert a salutation string as a new top line in the TRichEdit, followed by two blank lines. This is used by the email system to personalise the email and also works well.

The problem is that if the user formats the first lines of their body text when they enter it, for example suppose they make the first few lines a bulleted list, then the salutation line I add under code is also shown bulleted when the email arrives.

How can I use code to insert a line at the top of a TRichEdit with no paragraph or font formatting and yet preserve any formatting that the user might have applied to (what was) the first lines of their manual input?

The code I am using at the moment to insert my salutation string is below but my salutation still gets the formatting style that the user applies. (Originally I only had the three insert lines but added the other code following ideas in a similar question here ). Identifiers in upper case are constants defined elsewhere.

procedure AddRecipientVarableToBody( var Body: TRichEdit);
  begin  
  //remove formatting from the (new) first paragraph
  Thebody.Paragraph.Numbering := nsnone;
  Thebody.Paragraph.Alignment := taLeftJustify;

  //add the three new top lines (two blank plus a recipient)
  //done backwards as we insert a new line zero each time
  TheBody.lines.Insert(0,EMPTY_STRING);  // two blank lines
  TheBody.lines.Insert(0,EMPTY_STRING);
  TheBody.lines.Insert(0,'To: ' + RECIPIENT_VARIABLE_SALUTATION); 

 //Remove any formatting from first three lines
   TheBody.SelStart:=0;
   TheBody.SelLength:= length(TheBody.Lines[0]) + length(TheBody.Lines[1]) + length(TheBody.Lines[2]);
   TheBody.SelAttributes.Style  :=  [];
   end;

Addendum:

I managed a workaround to get the result I wanted by delaying the salutation insertion until I set up the parameters ready to pass to Indy and appending the entire TRichEdit HTML to a simple text string ie instead of

Params.Add('html=' +  GetHTML(body));

I used

Params.Add('html=' +  'To: ' + RECIPIENT_VARIABLE_SALUTATION + GetHTML(body)); 

where body is the TRichEdit.

However, I'd still like to know if my prioblem can be solved through the insertion of new lines into the TRichEdit directly.


Solution

  • You can define DefAttributes for your RichEdit. Then you can easily return to use this setup simply by

    RE.SelAttributes := RE.DefAttributes;
    

    So, here's a test of your situation. First defining the DefAttributes, e.g. in OnFormCreate():

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      // Initialize to what you want to return to, or use as default
      RE.DefAttributes.Charset := ANSI_CHARSET;
      RE.DefAttributes.Color := clBlack;
      RE.DefAttributes.Height := -16;
      RE.DefAttributes.Name := 'Segoe UI';
      RE.DefAttributes.Size := 12;
      RE.DefAttributes.Style := [];
    end;
    

    Note that above doesn't deal with bullets, they are handled separately.

    In following code we simulate what a user might have written ...

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      RE.Lines.Add('Final reminder');
      RE.Lines.Add('Please, fill the form below, and send it immediately.');
    
      RE.SelStart := 0;
      RE.SelLength := Length(RE.Lines[0]);
      RE.SelAttributes.Color := clRed;
      RE.SelAttributes.Name := 'Algerian';
      RE.SelAttributes.Size := 15;
    
      RE.SelStart :=  Length(RE.Lines[0]);
      RE.SelLength :=  Length(RE.Lines[1]);
      RE.SelAttributes := RE.DefAttributes;
    end;
    

    ... and what special attributes, Bold, Italic, Underline and Strikeout they might have added as well as a bullet for the first line. These are added with buttons in my test form.

    enter image description here

    Finally how to add the three lines to the beginning and assure an independent formatting.

    procedure AltAddRecipientVarableToBody( var RE: TRichEdit);
    begin
      RE.lines.Insert(0,EMPTY_STRING);  // two blank lines
      RE.lines.Insert(0,EMPTY_STRING);
      RE.lines.Insert(0,'To: ' + RECIPIENT_VARIABLE_SALUTATION);
    
      // Select
      RE.SelStart := 0;
      RE.SelLength:= length(RE.Lines[0]) + 1
                   + length(RE.Lines[1]) + 1
                   + length(RE.Lines[2]) + 1;
      // Clear attributes
      RE.SelAttributes := RE.DefAttributes;
      // Clear bullets
      RE.Paragraph.Numbering := nsNone;
    end;
    

    The addition of 1 char per line is for the new line characters. Note that, since bullets are properties of paragraphs, they can not be defined in DefAttributes and must be dealt with separately.

    enter image description here

    And the result, with the three added lines formatted with DefAttributes and the original text maintaining whatever formatting it had.