|
Визуальный HTML редактор своими руками.
Часть II.
В прошлый раз речь шла о том, как работать с текстом в HTML редакторе. В этот раз мы поговорим о том, как работать с другими объектами HTML страниц - контролами. К ним относятся всевозможные элементы управления, изображения, фреймы, таблицы.
Рассмотрим общий принцип работы с этими элементами. Как и в
случае с текстом, прежде всего надо создать объект-выделение
(назовем его Range):
Range: IHTMLControlRange;
Интерфейс IHTMLControlRange предназначен специально для
выполнения различных операций с выделенными объектами страницы,
однако, его совершенно невозможно применять для работы с
текстовым выделением - вы получите исключительную
ситуацию EIntfCastError с сообщением о том, что выбраннй
интерфейс не поддерживается (тоже самое будет, если
использовать IHTMLTxtRange для работы с контролами). Чтобы
избегать подобных ситуаций, в интерфейсе IHTMLSelectionObject
введено поле Type_: widestring. В зависимости от типа выделения оно
будет содержать 'Control' или 'Text' (если ничего не выделено, то это поле будет содежать 'None'). Вот простой пример того, как
можно вставить картинку в определенное место документа (как открыть
документ в режиме редактирования было описано в первой
статейке):
procedure TForm1.SpeedButton13Click(Sender: TObject);
var
CtrlRange: IHTMLControlRange;
TextRange: IHTMLTxtRange;
begin
if editor.selection.type_='Control' then
begin
CtrlRange:=(editor.selection.createRange as IHTMLControlRange);
if not CtrlRange.queryCommandEnabled('InsertImage') then
Application.MessageBox('Not Supported!','');
else
CtrlRange.execCommand('InsertImage',false,'C:\my files\porshe1.jpg')
end
else begin
TextRange:=(editor.selection.createRange as
IHTMLTxtRange); TextRange.execCommand('InsertImage',false,'C:\my
files\porshe1.jpg') end;
end;
Обратите внимание на то, что когда веделен объект,
мы используем метод queryCommandEnabled чтобы убедиться, что данную
комманду можно выполнить над выделенным контролом. Это связано
с тем, что, например, встроенный фрейм нельзя заменить на
картинку. На самом деле это проверка необязательная, но я все же
рекомендую её проводить во избежание неприятных последствий. Еще
один метод - queryCommandSupported(CmdID: WideString): boolean
позволяет выянить, поддерживается ли данная комманда данным типом
выделения. Такие же методы есть и у интерфейса IHTMLTxtRange,
но в данном случае в них нет
необходимости.
С таблицами дело обстоит гораздо сложнеее. Контролы
типа HTMLTable, HTMLRow и HTMLCell, согласно документации от Microsoft,
предназначены для создания таблиц при формировании страницы на
стороне сервера. Соответсвенно, в нашем случае возникают некоторые
трудности: в частности, как добавить полученную таблицу в документ
(во всяком случае, у меня ничего не вышло). Как вариант я предлагаю
следующее: создавать таблицу типа HTMLTable, работать с ней так, как
будто мы формируем документ на сервере, а затем, использовать свойство
OuterHTML. Это поле содержит текстовое представление таблицы в формате
HTML. Рассмотрим подробнее этот способ на примере:
procedure TForm1.SpeedButton14Click(Sender: TObject);
var
Table: HTMLTable;
TextRange: IHTMLTxtRange;
row: HTMLTableRow;
Col: HTMLTableCol;
i: integer;
begin
if editor.selection.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.selection.createrange as IHTMLTxtRange);
textrange.pasteHTML(table.OuterHTML);
end;
end;
На мой взгляд, этот пример достаточно информативен. Очевидное преимущество
использования объекта HTMLTable и сопутствующих ему объектов состоит в том, что программисту
не надо беспокоится о том, как описать на HTML то или иное свойство таблицы, нет
необходимости работать со строками, писать парсеры и т.п. - таблица сама себя опишет. Однако,
очевидным недостатком такого метода является то, что в последствии невозможно будет обратиться
к созданной таблице как к объекту, и изменить её програмным методом (использование парсеров и
интерпритаторов кода в расчет брать не будем).
[Дополнение от 27.07.2004:
Я еще несколько раз прочитал MSDN и нашел таки способ нормально работать с таблицами и ячейками.
Вот простой пример того, как можно заменить текст в уже созданной таблице:
var
i, j: integer;
ovTable: OleVariant;
t: HTMLTable;
begin
// В документе должна быть таблица, описанная примерно так:
//<table ... id="MyTable">
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;
То есть теперь у нас есть возможность как получать данные из таблицы, так и заносить их туда
в любой момент времени. Все свойства соответствуют свойствам DOM. Остается только сказать, что таким образом можно работать и с
формами, и с изображениями, в общем со всем, что поддерживается в Объектной модели докумета (DOM).] Если вы знаете более изящный способ работы с
таблицами, или можете чем-то дополнить изложенное выше, очень прошу вас написать мне на e-mail
: Samum2000@mail15.com
|