Разрабатываю небольшой компонент – текстовый редактор DBTextEditor, для своей программы . В базе данные будут храниться в HTML формате в обычном текстовом поле. У меня MySQL, я использую TEXT поле. Изображения будут храниться рядом с EXE – в отдельной папке Pics, а в базе будут только ссылки на изображение – что избавит от раздутия таблиц при использовании BLOB полей. Компонент разрабатываю с помощью фрэйма. То есть, доступ ко всем полям и методам будет примерно таким
1 |
DBTextEditor.VisualFrame.SomeMethod |
Выглядит фрэйм примерно таким образом
На фрэйме у нас TRichViewEdit – для отображения форматированного текста и TMemo для отображения HTML кода. По кнопке HTML будем переключать туда – обратно.
Базовый класс основного компонента – TPanel. Этот фрэйм размещается в главном модуле компонента примерно так…
1 2 3 4 5 6 7 8 9 10 |
constructor TDBTextEditor.Create(AOwner: TComponent); begin inherited; FVisualFrame:=TVisualFrame.Create(Self); FVisualFrame.Parent:=Self; FVisualFrame.Align:=alClient; FVisualFrame.Show; end; |
Параллельно сделана тестовая программа. Обычное VCL приложение. Выглядит это примерно так…
В тестовой программе инициируем работу с компонентом в FormCreate – подключаем к базе данных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
procedure TfTestDBtextEditor.FormCreate(Sender: TObject); var HTML:string; begin DBTextEditor1.VisualFrame.HTMLClick:=OnHTMLClick; with DBTextEditor1.VisualFrame do begin FDConnection:=Self.FDConnection; FDTable.TableName:='coffeetest_db.users'; FDConnection.Connected:=true; FDTable.Active:=true; DataSource.DataSet:=FDTable; RichViewEdit.Add('SomeText',0); RichViewEdit.ReformatAll; end; LoadHTMLContentFromDB(HTML); ShowHTMLContentInControls(HTML); end; |
Здесь описаны 2 метода
1 2 |
LoadHTMLContentFromDB(HTML); ShowHTMLContentInControls(HTML); |
Подробнее разберем их
LoadHTMLContentFromDB
1 2 3 4 5 6 7 8 9 10 11 |
procedure TfTestDBtextEditor.LoadHTMLContentFromDB(var HTML:string); begin with DBTextEditor1.VisualFrame.qLoadHTML do begin SQL.Text:='Select*from coffeetest_db.users where id=:id'; Params.ParamValues['id']:=1; Open; HTML:=FieldByName('TextContent').AsString; Close; end; end; |
ShowHTMLContentInControls
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
procedure TfTestDBtextEditor.ShowHTMLContentInControls(HTML:string); var s:string; PathForPics: string; begin //if not DBTextEditor1.VisualFrame.IsHTML then if DBTextEditor1.VisualFrame.HTMLMemo.Visible then begin DBTextEditor1.VisualFrame.HTMLMemo.Text:=HTML; DBTextEditor1.VisualFrame.pFontSettings.Hide; end else begin PathForPics:=ExtractFileDir(Application.ExeName)+'\'+'Pics'+'\'; DBTextEditor1.VisualFrame.RvHtmlImporter.BasePath:=PathForPics; DBTextEditor1.VisualFrame.RvHtmlImporter.LoadHtml(HTML); DBTextEditor1.VisualFrame.RichViewEdit.Format; DBTextEditor1.VisualFrame.pFontSettings.Show; end; end; |
Обработка HTML Click
Эта кнопка будет переключать HTML код на форматированное отображение и обратно. Теперь, для того, чтобы нам это переключение обработать извне – создадим событие при нажатии на кнопку в самом компоненте в модуле uVisualFrame
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
... private FHTMLClick:TNotifyEvent; property HTMLClick:TNotifyEvent read FHTMLClick write FHTMLClick; ... procedure TVisualFrame.bHTMLClick(Sender: TObject); begin if HTMLMemo.Visible then begin HTMLMemo.Hide; RichViewEdit.Show; bHTML.Caption:='HTML' ; ISHTML:=true; end else begin HTMLMemo.Show; RichViewEdit.Hide; bHTML.Caption:='Text'; ISHTML:=false; end; if Assigned(HTMLClick) then HTMLClick(Self); end; |
В тестовой же программе обработаем событие таким образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
procedure TfTestDBtextEditor.OnHTMLClick(Sender: TObject); var HTML:string; begin //Сохраняем контент в зависимости от того, что открыто SaveHTMLFromRichView; //Загружаем контент из базы LoadHTMLContentFromDB(HTML); // Отображаем контент ShowHTMLContentInControls(HTML); end; |
Само сохранение контента в зависимости от того – что открыто – выглядит следующим образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
procedure TfTestDBtextEditor.SaveHTMLFromRichView; var s:string; ss:TStringStream; PathForPics:string; ApplicationPath: string; begin //Определяем PathForPics PathForPics:=ExtractFileDir(Application.ExeName)+'\'+'Pics'+'\'; // ShowMessage(PathForPics); if not TDirectory.Exists(PathForPics) then TDirectory.CreateDirectory(PathForPics); if not DBTextEditor1.VisualFrame.IsHTML then begin ss:=TStringStream.Create; ss.Position:=0; // ShowMessage(PathForPics); DBTextEditor1.VisualFrame.RichViewEdit.SaveHTMLToStreamEx(ss,PathForPics,'','pic','','','',[rvsoOverrideImages]); s:=ss.DataString; DBTextEditor1.VisualFrame.FDTable.Edit; DBTextEditor1.VisualFrame.FDTable.FieldByName('TextContent').AsString:=s; DBTextEditor1.VisualFrame.FDTable.Post; end else begin DBTextEditor1.VisualFrame.FDTable.Edit; DBTextEditor1.VisualFrame.FDTable.FieldByName('TextContent').AsString:= DBTextEditor1.VisualFrame.HTMLMemo.Text; DBTextEditor1.VisualFrame.FDTable.Post; end; end; |
Результат
Теперь смотрим HTML код
В MySQL это выглядит примерно следующим образом
То есть всё корректно сохранилось.
Как и где сохранилась картинка?
Почему здесь?
В процедуре SaveHTMLFromRichView мы использовали следующий код
1 2 3 4 |
... DBTextEditor1.VisualFrame.RichViewEdit. SaveHTMLToStreamEx(ss,PathForPics,'','pic','','','',[rvsoOverrideImages]); ... |
Что это означает?
2-й параметр – это место, где мы сохраняли картинки, а именно
1 2 3 4 5 6 7 8 |
//Определяем PathForPics PathForPics:=ExtractFileDir(Application.ExeName)+'\'+'Pics'+'\'; // ShowMessage(PathForPics); if not TDirectory.Exists(PathForPics) then TDirectory.CreateDirectory(PathForPics); |
Параметр
1 |
rvsoOverrideImages |
также важен – он означает возможность перезаписывать картинки с одинаковыми именами, в результате – если мы несколько раз один и тот же файл загружаем – у нас будет только одна копия.
Можно ли редактировать в HTMLMemo?
Можно, и при переключении сохранение будет происходить через базу. В результате, когда откроем визуальную часть – все изменения будут отображены.
Выводы
Все работает корректно – но в пределах локального компьютера. Если нужен только локальный вариант программы, тогда это самое то. Мне же, как я понял впоследствии, нужна подгрузка изображений и файлов из WEb – а это несколько другая история, которая будет рассмотрена в одном из следующих постов.
В принципе, можно будет развить эту идею и при желании сделать небольшой HTML редактор – с TRichView это не так-то и сложно – как оказалось !!!