Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Convert Simple RichText to HTML tags in Delphi?

You may say that there are lots of discussions about this in stackOverflow, but most of them are more complicated than what I need and mostly for other languages.

I have a MySQL remote database in which I have a "Help" table with the code for filling the help pages of the dynamic web site that uses this database.

I decided to make a Delphi application to manage that website instead of doing by the web site itself for more speed and security.

I want to put a TRichEdit to make that help text and use simple things like alignment, bold, italic and underlined styles. I don't want to use pictures and fonts.

How to pick that rich styled text and convert it to HTML to put to my BLOB field in the remote database and then reconvert to rich text if I want to edit it again?

like image 462
NaN Avatar asked Aug 14 '12 14:08

NaN


2 Answers

If you really want to generate RTF content using a TRichEdit, then you should store the native RTF it generates alongside the converted HTML. If the only reason you are using TRichEdit is so that you can have simple formatting capabilities, then you are probably better off using an HTML edit control that generates native HTML content.

Regardless of which way you go, it is best to store the native format for users to edit the content, and convert it as needed to other formats (instead of converting it both directions).

If you use TRichEdit, then you can easily stream the RTF content in and out of the control, although I recommend TJvRichEdit over TRichEdit:

procedure GetRTFData(MS: TMemoryStream; RTF: TRichEdit);
begin
  MS.Clear;
  RTF.Lines.SaveToStream(MS);
  MS.Position := 0;
end;

procedure SetRTFData(MS: TMemoryStream; RTF: TRichEdit);
begin
  MS.Position := 0;
  RTF.StreamFormat := sfRichText;
  RTF.Lines.LoadFromStream(MS);
end;

Manually converting RTF to HTML is not an easy task. There are unicode character considerations, font styles, font codes, paragraph formatting, numbered lists, special HTML characters, and SO much more. Even though you only need to support simple formatting, users often use other features that cause conversion headaches -- like copying content from MSWord and pasting it into your app with all sort of formatting and font styles.

JvRichEditToHtml does a decent job converting RTF to HTML, but we ended up writing our own conversion unit because we do a lot more with RTF than simple formatting. JvRichEditToHtml should easily handle what you've described as long as users don't introduce complex content via a copy/paste, or use the keyboard shortcuts to format the content (e.g., bullets = ctrl+shft+L, indent = ctrl+M, etc.).

There are also several good HTML edit controls for Delphi if you want to bypass the complexities of authoring in RTF and converting to HTML:

Google Results :: Delphi, HTML, Editor, Component

  • HTML Editor for CBuilder/Delphi
  • WYSIWYG HTML Editor Component for Delphi
  • The quest for an HTML editor VCL control

Stack Overflow :: Delphi, HTML, Editor, Component

  • Delphi with HTML/CSS interface
  • (and many others!)

We use TRichView because of its extensive capabilities. It can load/create RTF, and export HTML. It isn't free however. If you are looking for something free, TJvRichView and JvRichEditToHtml are good options.

like image 83
James L. Avatar answered Nov 03 '22 04:11

James L.


After trying many different solutions which did not gave accurate results, I was inspired by this solution: Convert RTF to HTML and HTML to RTF.

The idea is that TWebBrowser control (in design/edit mode) can handle and convert correctly Rich text format when it was pasted from the clipboard.

uses SHDocVw, MSHTML;

function ClipboardToHTML(AParent: TWinControl): WideString;
var
  wb: TWebBrowser;

  function WaitDocumentReady: Boolean;
  var
    StartTime: DWORD;
  begin
    StartTime := GetTickCount;
    while wb.ReadyState <> READYSTATE_COMPLETE do
    begin
      Application.HandleMessage;
      if GetTickCount >= StartTime + 2000 then // time-out of max 2 sec
      begin
        Result := False; // time-out
        Exit;
      end;
    end;
    Result := True;
  end;
begin
  Result := '';
  wb := TWebBrowser.Create(nil);
  try
    wb.Silent := True;
    wb.Width := 0;
    wb.Height := 0;
    wb.Visible := False;
    TWinControl(wb).Parent := AParent;
    wb.HandleNeeded;
    if wb.HandleAllocated then
    begin
      wb.Navigate('about:blank');
      (wb.Document as IHTMLDocument2).designMode := 'on';
      if WaitDocumentReady then
      begin
        (wb.Document as IHTMLDocument2).execCommand('Paste', False, 0);
        Result := (wb.Document as IHTMLDocument2).body.innerHTML;
      end;
    end;
  finally
    wb.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  RichEdit1.SelectAll;
  RichEdit1.CopyToClipboard;

  ShowMessage(ClipboardToHTML(Self));
end;
like image 6
kobik Avatar answered Nov 03 '22 04:11

kobik