Візуальний html редактор своїми руками, приклади на delphi, статті, програмування -

Нам знадобиться зовсім небагато. В першу чергу - delphi 5-7 (у мене стоїть 7-я версія, і весь код тестувався саме в цій версії). Таке обмеження версій викликано тим, що компонент twebbrowser вперше "прописався" на вкладці internet саме в 5-й версії (в 4-й його треба було встановлювати як компонент activex). Ще необхідно, щоб в системі був встановлений internet explorer 4 і вище, з тих причин, що саме його частині є основою webbrowser'a.

Перевіримо це! Створимо нову форму, розмістимо на ній компоненту twebbrowser і кілька компонент tspeedbutton. Потім напишемо такий код: unit main;

var
form 1: tform 1;
disp: idispatch;
editor: ihtmldocument2;

procedure tform 1.webbrowser1documentcomplete (sender: tobject;
const pdisp: idispatch; var url: olevariant);
var
currentwb: iwebbrowser;
editor: ihtmldocument2;
begin
disp: = pdisp;
end;

procedure tform 1.speedbutton1click (sender: tobject);
var
currentwb: iwebbrowser;
begin
currentwb: = disp as iwebbrowser;
editor: = (currentwb.document as ihtmldocument2);
editor.designmode: = 'on';

end;
procedure tform 1.form create (sender: tobject);
begin
webbrowser1.navigate ( 'about:');
end;

Стандарт поєднання клавіш

"Це, звичайно, добре, що є гарячі клавіші, але мені не хотілося б все їх запам'ятовувати" - можете сказати ви. Добре. Тоді давайте розберемо, як з delphi змусити webbrowser виконувати всі ці дії. Для цього є метод execcommand інтерфейсу ihtmltxtrange (він описаний в модулі mshtml_tlb). Розглянемо простий приклад. procedure tform 1.speedbutton2click (sender: tobject);
var
range: ihtmltxtrange;
begin
range: = (editor.select ion.createrange as ihtmltxtrange);
range.execcommand ( 'bold', false, emptyparam)
end;

Кілька слів про об'єкт range. Крім вже знайомого нам execcommand цей об'єкт має ще ряд властивостей і методів, деякі з яких зараз розглянемо.

Містить текст виділення (без тегів html)

Повний текст виділення

movestart (const unit_: widestring;
count: integer)

Переміщує початкову позицію виділення на count символів вправо (якщо count<0, то влево), unit_-единицы измерения смещения (чаще всего используется 'character': 1 символ). При этом конечная позиция не смещается.

Те ж саме, тільки для кінцевої позиції виділення.

pastehtml (const html: widestring);

Показує допомогу по команді, зазначеної в cmdid

Додаток.
доступні команди

Встановлює або отримує колір фону поточного виділення. value повинно містити ім'я кольору або його шеснадцітірічний rgb еквівалент (наприклад, # ffcc00).

Перемикає зображення тексту поточного виділення між напівжирним і нормальним.

Розглянемо загальний принцип роботи з цими елементами. Як і у випадку з текстом, перш за все треба створити об'єкт-виділення (назвемо його range):

Інтерфейс ihtmlcontrolrange призначений спеціально для виконання різних операцій з виділеними об'єктами сторінки, однак, його абсолютно неможливо застосовувати для роботи з текстовим виділенням - ви отримаєте виняткову ситуацію eintfcasterror з повідомленням про те, що Вибраний інтерфейс не підтримується (те ж саме буде, якщо використовувати ihtmltxtrange для роботи з контролю). Щоб уникати подібних ситуацій, в інтерфейсі ihtmlselect ionobject введено поле type_: widestring. Залежно від типу виділення воно буде містити 'control' або 'text' (якщо нічого не виділено, то це поле буде содежать 'none'). Ось простий приклад того, як можна вставити картинку в певне місце документа (як відкрити документ в режимі редагування було описано в першій статейці):

procedure tform 1.speedbutton13click (sender: tobject);
var
ctrlrange: ihtmlcontrolrange;
textrange: ihtmltxtrange;
begin
if editor.select ion.type _ = 'control' then
begin
ctrlrange: = (editor.select ion.createrange as ihtmlcontrolrange);
if not ctrlrange.querycommandenabled ( 'insertimage') then
application.messagebox ( 'not supported!', '');
else
ctrlrange.execcommand ( 'insertimage', false, 'c: my filesporshe1.jpg') end
else
begin
textrange: = (editor.select ion.createrange as ihtmltxtrange);
textrange.execcommand ( 'insertimage', false, 'c: my filesporshe1.jpg')
end;
end;

Зверніть увагу на те, що коли Веделя об'єкт, ми використовуємо метод querycommandenabled щоб переконатися, що дану комманду можна виконати над виділеним контролом. Це пов'язано з тим, що, наприклад, вбудований фрейм можна замінити на картинку. Насправді це перевірка необов'язкова, але я все ж рекомендую її проводити, щоб уникнути неприємних наслідків. Ще один метод - querycommandsupported (cmdid: widestring): boolean дозволяє вияніть, чи ця комманда даним типом виділення. Такі ж методи є і у інтерфейсу ihtmltxtrange, але в даному випадку в них немає необхідності.

З таблицями справа йде набагато сложнеее. Контроли типу htmltable, htmlrow і htmlcell, згідно з документацією від microsoft, призначені для створення таблиць при формуванні сторінки на стороні сервера. Відповідно, в нашому випадку виникають деякі труднощі: зокрема, як додати отриману таблицю в документ (у всякому разі, у мене нічого не вийшло). Як варіант я пропоную наступне: створювати таблицю типу htmltable, працювати з нею так, як ніби ми формуємо документ на сервері, а потім, використовувати властивість outerhtml. Це поле містить текстове представлення таблиці в форматі html. Розглянемо докладніше цей спосіб на прикладі: procedure tform 1.speedbutton14click (sender: tobject);
var
table: htmltable;
textrange: ihtmltxtrange;
row: htmltablerow;
col: htmltablecol;
i: integer;
begin
if editor.select ion.type_<>'Control' then
begin
table: = (editor.createelement ( 'table') as htmltable);
for i: = 0 to 3 do
begin
row: = (table.insertrow (i) as disphtmltablerow);
col: = (row.insertcell (0) as disphtmltablecol);
col.width: = '200';
col.style.bordercolor: = '# ff0000';
col.innertext: = 'Осередок #' + inttostr (i);
end;
table.style.bordercolor: = '# 00ff00';
textrange: = (editor.select ion.createrange as ihtmltxtrange);
textrange.pastehtml (table.outerhtml);
end;
end;

var
i, j: integer;
ovtable: olevariant;
t: htmltable;
begin
// У документі повинна бути таблиця, описана приблизно так:
//

ovtable: = webbrowser1.oleobject.document. getelementsbyname ( 'mytable'). item (0);
//webbrowser1.oleobject.document. getelementsbyname ( 'mytable') -
// це колекція елементів (адже кілька елементів можуть мати
// id рівний "mytable"
for i: = 0 to (ovtable.rows.length - 1) do
for j: = 0 to (ovtable.rows.item (i) .cells.length - 1) do
ovtable.rows.item (i) .cells.item (j) .innertext: = 'new text!';
end;