C# WebBrowser - такой простой и такой сложный. Часть 1: HTML Editor
Элемент управления WebBrowser очень часто является хорошим вариантом для решения задач, связанных с Web Mining, отображением и работе с HTML данными. Несмотря на кажущуюся простоту работы с этим элементом управления, существует много проблем. На форумах очень часто можно встретить вопросы по работе с WebBrowser, на некоторые из наиболее часто задаваемых попробую ответить, а также расскажу о других приемах / трюках, с которыми пришлось столкнуться.
Работаем с WebBrowser в Windows Forms приложениях
Создадим Windows Forms приложение, в которое добавим для начала элементы управления WebBrowser, Button и RichTextbox. Первое, что сделаем - это загрузим какую-нибудь веб-страницу по умолчанию при запуске приложения. Для этого в методе Form1_Load напишем:
private void Form1_Load(object sender, EventArgs e) { webBrowser.Navigate("http://m.bing.com/"); }
После чего получим такой результат:
Шаблон проекта создан, приступим к выполнению некоторых задач.
Создание HTML Editor
Мы все привыкли к онлайн-редакторам HTML, но если нам необходимо сделать это в Windows Forms приложении? WebBroser может нам помочь в этом.
В первую очередь мы должны добавить в проект ссылку на Microsoft.mshtml, после чего перепишем наш код таким образом:
private void Form1_Load(object sender, EventArgs e) { InitWebBrowser(); } private void InitWebBrowser() { string Encoding = "ISO-8859-1"; HtmlDocument hd; mshtml.IHTMLDocument2 axObj; webBrowser.DocumentText = ""; webBrowser.Document.Encoding = Encoding; hd = webBrowser.Document; axObj = hd.DomDocument as mshtml.IHTMLDocument2; axObj.designMode = "On"; webBrowser.Navigate("http://m.bing.com/"); }
C виду он кажется очень простым, но на самом деле каждая строчка здесь имеет большое значение (когда пришлось долго попотеть, чтобы заставить этот код работать). Сначала мы создаем переменные типа mshtml.IHTMLDocument2 и HtmlDocument. Дальше присваиваем свойству DocumentText пустое значение - если мы этого не сделаем, то на следующей строчке мы получим исключение NullReferenceException и сообщением "В экземпляре объекта не задана ссылка на объект". На самом деле, мы не можем работать с свойством webBrowser.Document до того, как оно не проинициализируется. Самый простой способ - присвоить пустую строку свойству DocumentText или написать что-то типа webDrowser.Navigate("about:blank").
Нужно еще заметить, что многие свойства WebBrowser являются COM объектами, т.е. по сути WebBrowser - это обвертка (wrapper) над более старым элементом управления AxSHDocVw.AxWebBrowser. Поэтому следующим этапом является приведение hd.DomElement к интерфейсу mshtml.IHTMLDocument2. дальше мы добрались до самой сути - изменение режима браузера с помощью строки axObj.designMode = "On";
После этого наша страница будет редактируемой (добавим строку "Welcome from WebBrowser Demo!"):
Рассмотрим как можно менять стили в нашем HTML Editor.
Расширяем функционал HTML Editor
Понятно, что в таком виде наш редактор никому не нужен, поэтому добавим ему немного функционала.
Для этого нам необходимо разобраться, как можно управлять содержимым веб-браузера программно. А сделать это можно с помощью команды ExecCommand класса HtmlDocument, но для этого необходимо знать, какие параметры необходимо передавать.
Рассмотрим синтаксис метода execCommand, который принимает на вход три аргумента:
- имя команды: указывает на действия, которые необходимо совершить с выделением.
- флаг: булево значение, указывающее отображать ли интерфейс пользователя, вызванный командой.
- параметры команды
Из этих трех аргументов обязательным является только первый. Пример:
Список команд:
Команда | Описание |
2D-Position | Команда, позволяющая пользователю передвигать абсолютно позиционированные элементы. |
AbsolutePosition | Команда, устанавливающая свойство position данного элемента в значение "absolute". |
BackColor | Команда, устанавливающая или возвращающая цвет фона данного выделеного текста. |
BlockDirLTR | Не поддерживается. |
BlockDirRTL | Не поддерживается. |
Bold | Команда, переключающая состояние шрифта выделенного фрагмента текста между жирным и нормальным. |
BrowseMode | Не поддерживается. |
Copy | Команда, помещающая копию данного выделенного фрагмента текста в буфер обмена. |
CreateBookmark | Команда, создающая "якорь" из выделенного фрагмента текста или возвращает имя "якоря" для выделенного фрагмента текста. |
CreateLink | Команда, создающая гиперссылку из выделенного фрагмента текста. |
Cut | Команда, помещающая копию данного выделенного фрагмента текста в буфер обмена и удаляющая этот фрагмент из документа. |
Delete | Команда, удаляющая выделенный фрагмент текста. |
DirLTR | Не поддерживается. |
DirRTL | Не поддерживается. |
EditMode | Не поддерживается. |
FontName | Команда, задающая или возвращающая имя шрифта текста. |
FontSize | Команда, задающая или возвращающая размер шрифта текста |
ForeColor | Команда, задающая или возвращающая цвет текста. |
FormatBlock | Команда, форматирующая выделенный фрагмент текста как блок "DIV", "P" или "SPAN". |
Indent | Команда, увеличивающая отступ выделенного фрагмента текста. |
InlineDirLTR | Не поддерживается. |
InlineDirRTL | Не поддерживается. |
InsertButton | Команда, вставляющая в документ кнопку("BUTTON"). |
InsertFieldset | Команда, вставляющая в документ группу "FIELDSET". |
InsertHorizontalRule | Команда, вставляющая в документ горизонтальную полосу прокрутки. |
InsertIFrame | Команда, вставляющая в документ "плавающий" фрейм. |
InsertImage | Команда, вставляющая в документ изображение. |
InsertInputButton | Команда, вставляющая в документ командную кнопку. |
InsertInputCheckbox | Команда, вставляющая в документ кнопку-"флажок". |
InsertInputFileUpload | Команда, вставляющая в документ элемент управления для отправки файла на сервер. |
InsertInputHidden | Команда, вставляющая в документ скрытое поле. |
InsertInputImage | Команда, вставляющая в документ изображение как элемент управления. |
InsertInputPassword | Команда, вставляющая в документ поле ввода пароля. |
InsertInputRadio | Команда, вставляющая в документ радиокнопку. |
InsertInputReset | Команда, вставляющая в документ кнопку сброса данных формы. |
InsertInputSubmit | Команда, вставляющая в документ кнопку отправки данных из формы на сервер. |
InsertInputText | Команда, вставляющая в документ поле ввода текста. |
InsertMarquee | Комманда, вставляющая в документ прокручивающийся текст. |
InsertOrderedList | Комманда, вставляющая в документ нумерованный список. |
InsertParagraph | Комманда, создающая абзац из выделенного фрагмента текста. |
InsertSelectDropdown | Комманда, вставляющая в документ выпадающий список. |
InsertSelectListbox | Комманда, вставляющая в документ список. |
InsertTextArea | Комманда, вставляющая в документ область редактирования текста. |
InsertUnorderedList | Комманда, вставляющая в документ маркированный список. |
Italic | Комманда, переключающая состояние шрифта выделенного фрагмента текста между наклонным и нормальным. |
JustifyCenter | Комманда, выравнивающая абзац, в который входит фрагмент выделенного текста, по центру. |
JustifyFull | Не поддерживается. |
JustifyLeft | Комманда, выравнивающая абзац, в который входит фрагмент выделенного текста, по левому краю. |
JustifyNone | Не поддерживается. |
JustifyRight | Комманда, выравнивающая абзац, в который входит фрагмент выделенного текста, по правому краю. |
LiveResize | Комманда, включающая или выключающая режим мгновенного("живого") отображения размеров или местоположения элементов страницы во время изменения размеров последней. |
MultipleSelection | Комманда, позволяющая или запрещающая выделение сразу нескольких элементов web-строницы. |
Open | Не поддерживается. |
Outdent | Комманда, уменьшающая отступ выделенного фрагмента текста. |
OverWrite | Комманда, переключающая режим ввода текста между вставкой и заменой. |
Paste | Комманда, заменяющая данный выделенный фрагмент текста на содержимое буфера обмена. |
PlayImage | Не поддерживается. |
Комманда, открывающая диалоговое окно "Печать". | |
Redo | Не поддерживается. |
Refresh | Комманда, перезагружающая данный документ с сервера. |
RemoveFormat | Комманда, удаляющая все тэги форматирования текста из выделенного фрагмента текста. |
RemoveParaFormat | Не поддерживается. |
SaveAs | Комманда, сохраняющая текущую web-страницу в файл. |
SelectAll | Комманда, выделяющая весь документ. |
SizeToControl | Не поддерживается. |
SizeToControlHeight | Не поддерживается. |
SizeToControlWidth | Не поддерживается. |
Stop | Не поддерживается. |
StopImage | Не поддерживается. |
StrikeThrough | Не поддерживается. |
Subscript | Не поддерживается. |
Superscript | Не поддерживается. |
UnBookmark | Комманда, удаляющая элемент закладки из текущего фрагмента выделенного текста. |
Underline | Комманда, устанавливающая подчёркивание для выделенного фрагмента текста или снимающая это подчёркивание. |
Undo | Не поддерживается. |
Unlink | Комманда, удаляющая элемент гиперссылки из текущего фрагмента выделенного текста. |
Unselect | Комманда, очищающая данный фрагмент выделенного текста. |
Добавим обработчик события button1_Click и напишем:
private void button1_Click(object sender, EventArgs e) { HtmlDocument doc = webBrowser.Document; doc.ExecCommand("Bold", false, null); }
При запуске приложения вы можете выделить произвольный текст и установить стиль шрифта жирным путем нажатия на нашу кнопку. Таким образом вы можете написать полноценный HTML Editor, который будет поддерживать все команды форматирования.
Переход на новую страницу
И тут хочется рассказать об еще одной особенности работы с веб-браузером, на которую в свое время было потрачено очень много времени. Я говорю о ситуации, когда вам необходимо перейти на другой веб-сайт или загрузить новый шаблон для редактирования. Для демонстрации этой ситуации перепишем код button1_Click так, чтобы перенаправлять браузер на другую страницу, например на http://google.com/:
private void button1_Click(object sender, EventArgs e) { webBrowser.Navigate("http://google.com/"); }
В случае, если мы ничего не меняли в исходном шаблоне, переход при нажатии на кнопку пройдет успешно, но если вы хоть что-то поменяли в исходном документе, то при переходе вы увидите такое окно:
Я обшарил весь интернет в поисках решения, но ответа не нашел ни на одном из ресурсов, свойства типа ShowWarningPopup нет. В итоге решение пришло в виде такого трюка:
void ChangeAllowWebBrowserDrop() { webBrowser.AllowWebBrowserDrop = !webBrowser.AllowWebBrowserDrop; }
Эта функция изменяла свойство веб-браузера на противоположный, ее нужно вызывать перед тем как осуществлять переход на новую страницу. Вся соль в том, что простое присвоение true или false не помогает, необходимо каждый раз менять значение свойства на противоположный!
В следующих постах рассмотрим другие особенности работы с C# WebBrowser.
Компании из статьи
Microsoft Украина | Украинское подразделение компании Microsoft. |