Теперь уже пародия на серию книг “для чайнегов” (возможно и “для полных идиотов”) + на статьи в RSDN… ну и черт его знает, вдруг действительно какому-нибудь чайнегу поможет :)
Под катом статья про изменение параметров загрузки WebBrowser control в WinForms .NET 2.0 или как отключить картинки в веб-браузер компоненте.
Введение
Вопрос о том, как запретить отображение картинок или исполнение скриптов(например, JavaScript) в WebBrowser компоненте Windows Forms .NET 2.0 поднимался не раз и продолжает подниматься. Есть ни мало статей и примеров, показывающих как решить эту задачу, но они, как правило, касаются «оберток» вокруг mshtml. Бесспорно, WebBrowser также является оберткой, но для начинающего (или желающего сделать быстро) использовать готовый компонент будет наилучшим выходом, если бы не больной вопрос: «Как изменить параметры загрузки в…»
После того, как мне в очередной раз задали этот вопрос, я не удержался и пробежал по сайтам. Найденного материала вполне достаточно для решения проблемы, но меня озадачило сообщение с форума: «В .Net невозможно явным образом реализовать интерфейсы IDispatch и IUnknown, система COM Interop реализует их сама неявным образом. Следовательно, ваша реализация IDispatch не получит никаких вызовов». Тем не менее, решение есть. Я решил не усложнять ответ и попытался описать процесс как можно проще, но все-таки желательно ознакомиться со ссылками ниже. Заинтересованные в более детальном изучении, вполне могут проделать домашнюю работу самостоятельно.
Задача
Мы возьмем стандартный WebBrowser компонент и научим его изменять параметры загрузки документа. Для этого - заберемся под обертку WebBrowser и доберемся до ActiveX составляющей. Перекрывать Invoke не понадобится. Достаточно, при помощи атрибута [DispId (xxx)], указать метод с определенным DISPID.
ActiveXInstance
Что это такое? В MSDN это свойство описано как «Gets the underlying ActiveX WebBrowser control», т.е. «получить ActiveX, лежащий в основе WebBrowser компонента». Это то, что нужно. Забегая вперед, и делая наметки для будущего углубленного изучения, скажу, что ActiveXInstance можно привести к IOleObject или SHDocVw.IWebBrowser2.
Это то, что нужно. Но для чего? Для того чтобы WebBrowser использовал один из наших классов в качестве контейнера (client site). Во время исполнения, наш объект, в качестве контейнера, будет выдавать браузеру значения свойств, управляющих различными параметрами загрузки документа: разрешать или запрещать показывать картинки, исполнять или нет скрипты и Java и т.д. и т.п. Продолжаем, теперь уже в коде.
Реализация
Параметры загрузки
Для начала, перечислим параметры загрузки документа:
internal enum BrowserOptions : uint
{
None = 0,
AlwaysOffline = 0×10000000,
HearSounds = 0×00000040,
DisableActiveXRun = 0×00000200,
IgnoreCache = 0×00002000,
IgnoreProxy = 0×00004000,
ShowImages = 0×00000010,
DisableActiveXDownload = 0×00000400,
DisableBehaviours = 0×00008000,
DisableCharSets = 0×00010000,
DisableClientPull = 0×20000000,
DisableJava = 0×00000100,
DisableFrameDownload = 0×00080000,
DisableScripts = 0×00000080,
OfflineIfNotConnected = 0×80000000,
UTF8 = 0×00040000,
ShowVideos = 0×00000020
}
Я не стал описывать назначения параметров, их названия говорят сами за себя.
Контроллер параметров
Теперь непосредственно сам контроллер параметров. Именно его запрашивает браузер (в нашем случае WebBrowser компонент) и именно он объясняет браузеру, что показывать, а что нет.
[ComVisible(true)]
public class DownloadController : IOleClientSite
{
[DispId(-5512)]
public virtual int IDispatchInvokeHandler() {
return (int)(
BrowserOptions.ShowImages |
BrowserOptions.DisableScripts |
BrowserOptions.UTF8);
}
#region IOleClientSite Members
public int SaveObject() {
return 0;
}
public int GetMoniker(
uint dwAssign,
uint dwWhichMoniker,
out object ppmk) {
ppmk = null;
return 0;
}
public int GetContainer(out IOleContainer ppContainer) {
ppContainer = null;
return 0;
}
public int ShowObject() {
return 0;
}
public int OnShowWindow(int fShow) {
return 0;
}
public int RequestNewObjectLayout() {
return 0;
}
#endregion
}
Ставя целью написать как можно более простой пример, я вставил параметры загрузки непосредственно в код. В данном случае: отображать картинки, запретить исполнение скриптов (об этом параметре, ниже), использовать UTF8 для отправки адресов. В своем приложении Вы, конечно же, замените параметры переменной, значение которой будет формироваться в зависимости от настроек пользователя или всего приложения.
-5512
Использовать в коде «магических чисел» не есть хорошо. Правильно было бы написать так:
private const int DISPID_AMBIENT_DLCONTROL = -5512; [DispId(DISPID_AMBIENT_DLCONTROL)]
public virtual int IDispatchInvokeHandler() {
…
Браузер хранит некоторые параметры отображения документа, которые мы хотим изменить. Управление свойствами браузера реализовано через механизм свойств ActiveX, а именно через свойства контейнера (в нашем случае, это DownloadController). Запрос на получение этих свойств имеет идентификатор DISPID_AMBIENT_DLCONTROL, как раз равный магическому числу «-5512». Никакой магии.
Отметив метод IDispatchInvokeHandler атрибутом [DispId(DISPID_AMBIENT_DLCONTROL)] или [DispId(-5512)], мы говорим браузеру, что здесь будет приниматься вызов DISPID_AMBIENT_DLCONTROL и возвращаться свойства отображения документа.
IOLE… интерфейсы
Указать атрибут - мало, нужно чтобы класс контроллера поддерживал определенный интерфейс. Описание интерфейсов можно взять из исходных кодов приложенных к данной статье. После того как контроллер загрузки начал поддерживать интерфейс IOleClientSite, его можно «пристегнуть» к браузеру в качестве контейнера (client site).
Контроллер начинает работать
Осталось «пристегнуть» наш контроллер к WebBrowser.
IOleObject oleObject = webBrowser.ActiveXInstance as IOleObject;if (oleObject != null) {
oleObject.SetClientSite(
new DownloadController());
}
Не стоит вставлять эту часть кода в конструктор формы, например, где-то после InitializeComponent(), т.к. свойство ActiveXInstance «еще не готово».
Заключение
Все готово, задача решена. Мы получили искомый способ воздействия на WebBrowser, точнее на его параметры загрузки. Но этим возможности компонента не ограничены, есть еще большое поле для исследований и реализации.
В статье кратко описано, как же все-таки изменить параметры загрузки в Windows Forms WebBrowser .NET 2.0. Намеренно был пропущен момент с использованием COM-объектов в .NET, благодаря чему, описание получилось простым и доступным для начинающих. В статье не даны ответы на вопрос «почему так, а не иначе», но, тем не менее, она может быть использована как введение для дальнейшего углубленного изучения возможностей WebBrowser компонента в .NET 2.0.
Microsoft предупреждает
Описание проблемы
Разработчики часто используют MSHTML компонент InternetExplorer как HTML парсер без интерфейса пользователя («UI-less»). В случае, если включено исполнение скриптов, можно получить ряд проблем, включая отказ главного приложения.
Причина
MSHTML не предназначен для решения такой задачи (UI-less HTML парсер). Microsoft не поддерживает такое решение.
Решение
Microsoft рекомендует разработчикам, всегда отключать исполнение скриптов при использовании MSHTML в качестве UI-less HTML парсера.
Проблема встречается в Internet Explorer, начиная с версии 4.0 и заканчивая последней – 7.0.
Несмотря на то, что мы берем готовый компонент и слегка расширяем его, т.е. используем не как UI-less HTML парсер, проблема не исчезает. Ошибки нет-нет да появляются.
По теме
- Extended web browser control for .NET 1.0/1.1
- WebBrowserControl
- Extended .NET 2.0 WebBrowser Control
- Как изменить параметры загрузки документов?