У меня есть заметки в базе данных, хранящиеся в виде HTML с компонентом DHtml. Но я хочу изменить формат на RTF и использовать вместо него DevExpress TcxRichEdit, потому что я считаю, что это более простой компонент, более стабильный и т. Д. У пользователей возникают проблемы с исчезающими текстами, которые я, конечно, не могу воспроизвести.
TcxRichEdit работает нормально и может сохранять и загружать заметки снова.
Проблема в старых заметках в формате html.
Я пробовал эту процедуру , но так и не получил ее на работу.
Сгенерирована RTF-строка, но она не была принята TcxRichEdit.
Тогда у меня появилась идея использовать буфер обмена.
Имея DHtml и TcxRichEdit рядом, я должен скопировать и вставить между ними и позволить буферу обмена делать фактическое преобразование. На практике все оказалось не так просто, как я думал ...
Вот код:
function _ConvertToRtf(aHtml: String; aRichEdit: TcxRichEdit): Boolean;
begin
Result := False;
if (aHtml <> '') and (aHtml <> ' ') 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 возвращает False:
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;
Итак, я пробовал копать глубже и глубже в 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 и не работает?
Edit1:
Еще кое-что. Документы для html-компонента здесь http://www.profgrid.com/documentation/htmledit/
Кажется, команда stop останавливает загрузку HTML-страницы в элемент управления. Я использовал случайно, потому что в другом месте это предотвращает блокировку при загрузке данных в HTML. В любом случае было бы очень приятно получить преобразование и избавиться от компонента HTML!
Edit2:
Я наконец нашел решение, и это было довольно просто. Просто добавьте компонент Dhtml в форму во время разработки, а не создавайте его в коде. Таким образом, свойство busy было ложным, и оно просто работает. Нет необходимости проверять занятость в цикле while, как это делается в методе SetSource. Я ставлю jachquate галочку, когда он отмечает, что компонент был асинхронным. Окончательный код для преобразования строки выглядит следующим образом:
function _ConvertToRtf(aHtml: String; aRichEdit: TcxRichEdit): Integer;
begin
if (aHtml <> '') and (aHtml <> ' ') 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;
Спасибо за поддержку и приверженность моей проблеме!