Thursday, November 15, 2012

Inside the DOCU program (2) - saving and loading rich text

Yesterday I discussed the gross structure of the DOCU program; today I am going to concentrate on the 'entry' form.
Originally, the form contained a dbMemo component whose font was fixed at compile time. Obviously at some stage I received a request to change the component so that coloured and or bolded text could be stored. The dbMemo component doesn't allow this but the dbRichEdit component does. Fortunately for me, one of the demo programs which comes with Delphi is an editor based around a rich edit component, so I was able to extract from this demo most of the necessary interface code. With the use of the tool buttons, the user is able to choose type face, font size, bolding, italics, underlining and colour as well as numeration.

If everything were as easy as this, then I would be out of a job. The problems began when I wrote the code to store the text in the database; when the saved text was restored from the database, all the richness (ie fonts and colours) had been lost!

The answer is to be found here; unfortunately, there is no real explanation of why the code succeeds whereas the naive code fails. 

For loading the rtf text:

//Get the data from the database as AnsiString
rtfString:= sql.FieldByName ('rtftext').AsAnsiString;

//Write the string into a stream
stream:= TMemoryStream.Create;
stream.Clear;
stream.Write (PAnsiChar(rtfString)^, Length(rtfString));
stream.Position:= 0;

//Load the stream into the RichEdit
RichEdit.PlainText:= False;
RichEdit.Lines.LoadFromStream (stream);

stream.Free;

For saving the rtf text:
//Save to stream
stream:= TMemoryStream.Create;

stream.Clear;

RichEdit.Lines.SaveToStream (stream);
stream.Position:= 0;

//Read from the stream into an AnsiString (rtfString)
if (stream.Size >= 0) then
 begin
   SetLength(rtfString, stream.Size);
   if (stream.Read(rtfString[1], stream.Size) <= 0) then
   raise EStreamError.CreateFmt('End of stream reached with %d bytes left to read.', [stream.Size]);
end;

stream.Free;

//Save to database
sql.FieldByName('rtftext').AsAnsiString := rtfString;

No comments: