html - 将 HTML 转换为 RTF

标签 html delphi rtf

我在数据库中使用 DHtml 组件将注释存储为 html。但我想将格式更改为 RTF 并改为使用 DevExpress TcxRichEdit,因为我觉得这是一个更简单的组件,更稳定等。用户遇到了我当然无法复制的消失文本的问题。

TcxRichEdit 工作正常,可以再次保存和加载笔记。 问题是 html 格式的旧注释。 我试过this routine但我从来没有让它工作。 生成了一个 rtf 字符串,但 TcxRichEdit 不接受它。

然后我有了使用剪贴板的想法。 通过并排放置 DHtml 和 TcxRichEdit,我应该在它们之间进行复制和粘贴,让剪贴板进行实际转换。实际上并没有我想象的那么简单......

这是一些代码:

  function _ConvertToRtf(aHtml: String; aRichEdit: TcxRichEdit): Boolean;
  begin
    Result := False;
    if (aHtml <> '') and (aHtml <> '&nbsp;') then
    begin
      if not AnsiStartsStr('{\rtf1', aHtml) then
      begin
        vHtmlDlg.InitDoc := aHtml;
        vHtmlDlg.Editor.Stop;
        if vHtmlDlg.Editor.SelectAll then
          if vHtmlDlg.Editor.CutToClipboard then
          begin
            aRichEdit.Clear;
            aRichEdit.PasteFromClipboard;
          end;
      end;

      Result := True;
    end;
  end;

问题是 vHtmlDlg.Editor.SelectAll 总是返回 False。

function TCustomProfDHTMLEdit.SelectAll: Boolean;
const
  CGID_MSHTML: TGUID = '{DE4BA900-59CA-11CF-9592-444553540000}';
var
  D: IDispatch;
  CommandTarget: IOleCommandTarget;
  vaIn, vaOut: OleVariant;
  hr: HRESULT;
begin
  Result := False;
  if GetDOM(D) then
  try
    CommandTarget := D as IOleCommandTarget;
    hr := CommandTarget.Exec(@CGID_MSHTML, 31, OLECMDEXECOPT_DODEFAULT, vaIn, vaOut);
    Result := SUCCEEDED(hr)
  except
  end
end;

返回False的其实是GetDOM:

function TProfDHTMLEdit2.GetDOM(out P: IDispatch): Boolean;
begin
  if Busy then
  begin
    P := nil;
    Result := False
  end
  else
    try
      P := (IDispatch(GetOleObject) as IWebBrowser2).Document;
      Result := True
    except
      P := nil;
      Result := False
    end
end;

不,返回 true 的是 GetBusy...

function TProfDHTMLEdit2.GetBusy: Boolean;
begin
  if FDocumentCompleteReason <> dcrUndefined then
    Result := True
  else
    Result := False
end;

所以我已经尝试在 html 组件中进行更深入的挖掘,但我仍然不明白为什么我不能使用 SelectAll。

这是我如何初始化和使用它的简化版本。

  vHtmlDlg := TDhtmlEditorForm.Create(nil);
  vHtmlDlg.Show;
  vHtmlDlg.BrowseMode := False;
  try
   // Call ConvertToRtf with strings in a loop here 
  finally
    vHtmlDlg.Free;
  end;

知道为什么 SelectAll 返回 false 并且不起作用吗?

编辑1: 还有一件事。 html 组件的文档在此处 http://www.profgrid.com/documentation/htmledit/ 停止命令似乎停止将 HTML 页面加载到控件中。我偶然使用了它,因为在另一个地方它可以防止在以 html 加载数据时发生锁定。无论如何,获得转换并摆脱 HTML 组件真的很棒!

编辑2: 我终于找到了解决方案,而且非常简单。只需在设计时将 Dhtml 组件添加到表单中,而不是在代码中创建它。这样, busy 属性是错误的,它就可以正常工作。无需在 while 循环中检查忙,因为这是在 SetSource 方法中完成的。我给jachquate复选标记,因为他注意到我的组件是异步的。转换字符串的最终代码如下所示:

  function _ConvertToRtf(aHtml: String; aRichEdit: TcxRichEdit): Integer;
  begin
    if (aHtml <> '') and (aHtml <> '&nbsp;') then
    begin
      if not AnsiStartsStr('{\rtf1', aHtml) then
      begin
        DhtmlMemo.Source := aHtml;
        if DhtmlMemo.SelectAll then
          if DhtmlMemo.CutToClipboard then
          begin
            aRichEdit.Clear;
            aRichEdit.PasteFromClipboard;
          end;

        if VarIsNull(aRichEdit.EditValue) then
          Result := 0    // Not valid. The caller would delete the note.
        else
          Result := 2;   // String was converted
      end
      else
        Result := 1;     // String already in rtf. Do nothing.
    end
    else
      Result := 0;       
  end;

感谢您对我的问题的支持和 promise !

最佳答案

由于这是一次性转换,因此我同意您使用剪贴板。

HTML 组件看起来像一种Async 组件,因此您必须等待,因为它会在其他线程中处理加载/表示提供的 HTML,所有这些都由组件封装。我不知 Prop 体的组件,但我敢打赌这会起作用:

  function _ConvertToRtf(aHtml: String; aRichEdit: TcxRichEdit): Boolean;
  begin
    Result := False;
    if (aHtml <> '') and (aHtml <> '&nbsp;') then
    begin
      if not AnsiStartsStr('{\rtf1', aHtml) then
      begin
        vHtmlDlg.InitDoc := aHtml;
        vHtmlDlg.Editor.Stop;
        //before or after stop, I'm not sure what stop means
        while vHtmlDlg.Busy do
          Sleep(1); // or maybe Application.ProcessMessages, try both
        if vHtmlDlg.Editor.SelectAll then
          if vHtmlDlg.Editor.CutToClipboard then
          begin
            aRichEdit.Clear;
            aRichEdit.PasteFromClipboard;
            Result := True;  //of course you return true only if this succeeds.
          end;
      end;
    end;
  end;

如果这是要在用户计算机上完成的多次转换,请阅读 @Chris answer .

关于html - 将 HTML 转换为 RTF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5433881/

相关文章:

html - 嵌入框阴影 IE8

angularjs - ng-if 在 ng-repeat 中不起作用

delphi - 如何使用带有字符串索引的属性?

delphi - 如何影响 URL 来访问已注册的 Delphi WebService

delphi - 如何设置编辑的背景图像(Delphi)

javascript - Onclick 仅在第二次单击后才起作用

php - 自定义页面中标题之间的差距

java - 谁能推荐一个Java富文本编辑器?

vb.net - 了解 RTF 并使用 vb.net 进行编辑

ms-word - 如何提供 .RTF