2011-03-25 161 views
3

我在存儲爲html的DHtml組件中記錄了數據庫中的註釋。但我想將格式更改爲RTF,並使用DevExpress TcxRichEdit來代替,因爲我覺得這是一個更簡單的組件,更穩定等。用戶在消除文本方面存在問題,我當然無法重現。將HTML轉換爲RTF

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; 

它實際上是的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; 

不,它是GetBusy返回true ...

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

所以我試圖挖的更深depper 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/ stop命令似乎停止將HTML頁面加載到控件中。我偶然使用過,因爲在另一個地方它可以防止在html中加載數據時發生鎖定。無論如何,真正很好的獲得轉換並擺脫HTML組件!

編輯2: 我終於找到了解決方案,它非常簡單。只需在設計時將Dhtml組件添加到表單中,而不是在代碼中創建它。這樣繁忙的財產是錯誤的,它只是起作用。不需要在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; 

感謝您對我的問題的支持和承諾!

回答

2

由於這是一次性轉換,因此我與您一起使用剪貼板。

HTML組件看起來就像是一種異步成分的,所以你必須要等待,因爲它會被處理加載/代表其他線程提供的HTML,所有封裝的組件。我不知道具體的成分,但我敢肯定,這將工作:

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多時間轉換。

+0

是的,它是一個約700個需要轉換爲RTF格式的html字符串。有點無聊,做手動.... – 2011-03-26 06:33:36

+0

而且它不是在用戶機器上。它位於連接了許多用戶的服務器上。因此,當版本與新的Richedit組件一起更改時,我運行一個在數據庫中執行轉換的maintanance方法。之後,用戶可以登錄。 – 2011-03-26 06:49:37

+0

@羅蘭,你試過我的建議嗎?它看起來像你必須擺脫停止方法,只是等待(如建議),直到組件不再忙碌 – jachguate 2011-03-26 06:55:43

2

如果您在剪貼/複印之後延遲粘貼,您可能有機會。 但是一般來說,像這樣使用剪貼板是非常糟糕的做法。提供剪貼板是爲了方便用戶,而不是程序員。任何剪貼板感知程序都會對此作出反應,包括任何遠程桌面/ citrix會話,這些會話都將試圖通過網絡來傳播這種垃圾信息。

+0

我假設他正在寫一個小型的「轉換器」應用程序,他將運行一次,所以干擾其他應用程序不是一個問題 – 2011-03-26 11:13:36