Последнее обновление: 31.10.2015
WebBrowser предоставляет функции интернет-браузера, позволяя загружать и отображать контент из сети интернет. В то же время важно понимать, что данный
элемент не является полноценным веб-браузером, и возможности по его настройки и изменению довольно ограничены.
Рассмотрим основные его свойства:
-
AllowWebBrowserDrop: при установке для данного свойства значения
true
можно будет с помощью
мыши переносить документы в веб-браузер и открывать их. -
CanGoBack: определяет, может ли веб-браузер переходить назад по истории просмотров
-
CanGoForward: определяет, может ли веб-браузер переходить вперед
-
Document: возвращает открытый в веб-браузере документ
-
DocumentText: возвращает текстовое содержание документа
-
DocumentTitle: возвращает заголовок документа
-
DocumentType: возвращает тип документа
-
IsOffline: возвращает true, если отсутствует подключение к интернету
-
ScriptErrorsSuppressed: указывает, будут ли отображаться ошибки javascript в диалоговом окне
-
ScrollBarsEnabled: определяет, будет ли использоваться прокрутка
-
URL: возвращает или устанавливает URL документа в веб-браузере
Кроме того, WebBrowser содержит ряд методов, которые позволяют осуществлять навигацию между документами:
-
GoBack(): осуществляет переход к предыдущей странице в истории навигации (если таковая имеется)
-
GoForward(): осуществляет переход к следующей странице в истории навигации
-
GoHome(): осуществляет переход к домашней странице веб-браузера
-
GoSearch(): осуществляет переход к странице поиска
-
Navigate: осуществляет переход к определенному адресу в сети интернет
Таким образом, чтобы перейти к определенному документу, надо исользовать метод Navigate:
// перейти к адресу в интернете webBrowser1.Navigate("http://google.com"); // открыть документ на диске webBrowser1.Navigate("C://Images//24.png");
Создадим небольшй веб-браузер. Для этого поместим на форму элементы WebBrowser, TextBox (в него будем вводить адрес) и
Button. И в файле формы пропишем следующий код:
public partial class Form1 : Form { public Form1() { InitializeComponent(); // установка начального адреса webBrowser1.Url=new Uri("http://google.com"); button1.Click+=button1_Click; } private void button1_Click(object sender, EventArgs e) { webBrowser1.Navigate(textBox1.Text); } }
И по нажатию кнопки произойдет переход к адресу, введенному в текстовое поле:
C# Windows Forms: встроенный браузер без падений
Суть проблемы состоит в том, что браузерная компонента WebBrowser позволяет работать с содержимым страницы только после полной загрузки её DOM. Многие начинающие разработчики не учитывают этого и их программы с встроенным браузером «падают» немедленно после попытки получить элемент со страницы:
WebBrowser w = new WebBrowser(); w.Url = new Uri("https://google.com"); var e = w.Document.GetElementById ("elementId");
Скорее всего, здесь w.Document
равен null
, потому что переход браузера на новую страницу выполняется асинхронно, а строчка три сработает сразу после второй без ожидания загрузки страницы. Можно сделать вот так:
WebBrowser w = new WebBrowser(); public Form1() { InitializeComponent(); w.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler (w_DocumentCompleted); w.Url = new Uri("https://google.com"); } void w_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { var e = w.Document.GetElementById("elementId"); }
а ещё лучше применить вспомогательную функцию OpenUri
(см. в коде), которую можно вызывать, если при старте программы требуется загрузка web-страницы.
Создав проект C# Windows Forms, добавим на форму компоненты WebBrowser
и TextBox
с именами по умолчанию. Для реализации как автоматического сбора информации со страницы, загружаемой при старте приложения, так и перехода на страницу, адрес которой введён в TextBox
, нам понадобилось запрограммировать только следующие события:
Form1
(конструктор формы) — вызываемOpenUri
и разбираем другой вспомогательной функциейPrintDom
структуру документа на заданную глубину (в демо-целях выводится окно сообщенияMessageBox
). Также показано, как после вызоваOpenUri
извлечь отдельный элемент;textBox1_KeyDown
— по нажатию Enter в текстовом поле пытаемся минимально грамотно проверить, является строка вTextBox
адресом и затем переходим на неё;textBox1_Click
— по клику в текстовом поле выделяем его содержимое, чтобы сразу можно было вводить новый адрес.
Вспомогательные методы:
OpenUri
— ожидание загрузки страницы с заданным адресом. Кстати, в теле функции есть ответ на ещё один частый вопрос — «Как убрать сообщения об ошибках сценария при работе сWebBrowser
?»;PrintDom
— cканируем DOM на заданную глубинуdepth
и собираем всю информацию в строку.
Вот полный исходник файла Form1.cs
и проект для скачивания.
using System; using System.Windows.Forms; namespace MiniBrowser { public partial class Form1 : Form { public Form1 () { InitializeComponent (); OpenUri (textBox1.Text); //Ждём загрузки страницы! //Теперь можно получить элементы со страницы: HtmlDocument doc = webBrowser1.Document; if (doc != null) { HtmlElementCollection elemColl = doc.GetElementsByTagName ("HTML"); String str = PrintDom (elemColl, new System.Text.StringBuilder (), 1); MessageBox.Show ("DOM=" + str, "Тест Google", MessageBoxButtons.OK); } //Или конкретный элемент: /* HtmlElement el = webBrowser1.Document.GetElementById ("elementId"); if (el != null) { MessageBox.Show ("Элемент="+ el.ToString (), "Тест Google", MessageBoxButtons.OK); } */ } private void textBox1_KeyDown (object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { string url = textBox1.Text.Trim (); if (String.IsNullOrEmpty (url)) return; if (url.Equals ("about:blank")) return; //На пустое переходить не надо if (!url.StartsWith ("http://") && !url.StartsWith ("https://")) { //Дописать протокол по умолчанию url = "http://" + url; } Uri test = new Uri (url); if (Uri.TryCreate (url, UriKind.RelativeOrAbsolute, out test)) { try { webBrowser1.Navigate (test); } catch (System.UriFormatException ex) { MessageBox.Show (ex.Message, "Ошибка", MessageBoxButtons.OK); return; } } } } private void textBox1_Click (object sender, EventArgs e) { textBox1.SelectAll (); } private string PrintDom (HtmlElementCollection elemColl, System.Text.StringBuilder returnStr, Int32 depth) { //Сканируем DOM на заданную глубину depth System.Text.StringBuilder str = new System.Text.StringBuilder (); foreach (HtmlElement elem in elemColl) { string elemName; elemName = elem.GetAttribute ("ID"); if (elemName == null || elemName.Length == 0) { elemName = elem.GetAttribute ("name"); if (elemName == null || elemName.Length == 0) { elemName = "<no name>"; } } str.Append (' ', depth * 4); str.Append (elemName + ": " + elem.TagName + "(Level " + depth + ")"); returnStr.AppendLine (str.ToString ()); if (elem.CanHaveChildren) { PrintDom (elem.Children, returnStr, depth + 1); } str.Remove (0, str.Length); } return returnStr.ToString (); } private void OpenUri (string uri) { webBrowser1.ScriptErrorsSuppressed = true; //Убрать сообщения об ошибках сценария webBrowser1.Url = new Uri (uri); while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) { Application.DoEvents (); //Выполняем другие события, пока страница не загрузилась } } } }
Скачать проект C# Windows Forms «MiniBrowser» в архиве .zip, развернуть в новую папку (12 Кб)
Скриншот приложения в работе
07.11.2024, 15:02 [132 просмотра]
К этой статье пока нет комментариев, Ваш будет первым
Время на прочтение6 мин
Количество просмотров34K
Как известно, контрол WebBrowser это просто обертка над ActiveX компонентом Internet Explorer. Следовательно он предоставляет доступ к полноценному layout-движку со всеми современными плюшками. А раз так, то попробуем (сам не знаю правда зачем) на его основе сделать пользовательский интерфейс для обычного windows-приложения.
Можно, конечно, было бы запустить в этом же процессе мини веб-сервер (на HttpListener например) и ловить запросы через него, но это слишком просто, скучно и неспортивно. Попробуем обойтись без сетевых компонентов, just for fun.
Итак, задача проста — необходимо перехватывать отправку HTML-форм и выводить новый HTML-документ, сгенерированный логикой приложения в зависимости от POST-параметров.
Прежде всего нам понадобится Windows Forms Application с одной единственной формой на которой будет один единственный контрол — WebBrowser занимающий все пространство.
Для примера рисуем пару простых страниц интерфейса (с минимальным содержимым для краткости, а так скрипты и стили добавлять по вкусу).
Первая страница:
<!DOCTYPE html>
<html>
<head><meta http-equiv="X-UA-Compatible" content="IE=11"></head>
<body>
<form method="post">
<input type="text" name="TEXT1" value="Some text" />
<input type="submit" value="Open page 2" name="page2" />
</form>
</body>
</html>
Вторая страница:
<!DOCTYPE html>
<html>
<head><meta http-equiv="X-UA-Compatible" content="IE=11"></head>
<body>
<div>%TEXT1%</div>
<form method="post">
<input type="submit" value="Back to page 1" name="page1" />
</form>
</body>
</html>
Примечание: X-UA-Compatible необходим для корректного отображения некоторых стилей, в данном примере они не используются, но проблема есть. Не буду вдаваться в детали, но без этого компонент рисует страницы в режиме совместимости с чем то очень старым, со всеми вытекающими последствиями.
WebBrowser предоставляет несколько событий, среди которых есть например Navigating, которое срабатывает перед тем как отправить форму или перейти по ссылке.
Практически то что нужно, но это событие не предоставляет никакой информации о post-параметрах. GET-параметры использовать не получится поскольку у наших HTML-форм атрибут action отсутствует, что приведет к тому что в качестве URL всегда будет about:blank и никакой информации о GET параметрах не будет.
Для получения более подробной информации о запросе надо подписаться на событие BeforeNavigate2 (подробнее тут) у внутреннего COM-объекта браузера, благо он доступен через свойство ActiveXInstance.
Сделать это проще всего через dynamic, чтобы не возиться с объявлением COM-интерфейсов:
Объявляем делегат:
private delegate void BeforeNavigate2(object pDisp, string url, int Flags, string TargetFrameName, byte[] PostData, string Headers, ref bool Cancel);
Затем подписываемся на событие (в конструкторе формы у WebBrowser свойство ActiveXInstance будет null, потому это лучше сделать после того как окно загрузится, т.е. в OnLoad например):
((dynamic)webBrowser.ActiveXInstance).BeforeNavigate2 += new BeforeNavigate2(OnBeforeNavigate2);
Итак, в PostData лежат post-параметры в виде строки состоящей из пар ключ=значение объединенных через &. Разделяем их и укладываем в словарь:
var parameters = (PostData == null ? string.Empty : Encoding.UTF8.GetString(PostData))
.Split('&')
.Select(x => x.Split('='))
.Where(x => x.Length == 2)
.ToDictionary(x => WebUtility.UrlDecode(x[0]), x => WebUtility.UrlDecode(x[1]));
Кроме того, в этом обработчике лучше отменить действие через параметр Cancel, чтобы лишний раз не попадать на about:blank.
Имея параметры генерируем текст новой страницы. Сюда теоретически прикручивается какой-н менеджер обработчиков, выбирающий необходимый обработчик в зависимости от параметров, которые по каким-н шаблонам будут собирать страницы из кусочков, но для краткости пока для примера просто по кнопке page1 откроем первую страницу, по кнопке page2 — вторую (имена кнопок в разметке указывать обязательно, иначе из post-параметров не определить какую именно кнопку нажали), а также заменим все строки в круглых скобках на значения параметров с такими именами:
private static string Handler(IReadOnlyDictionary<string, string> parameters)
{
// do some useful stuff here
var newPage = "Not found";
if (parameters.ContainsKey(nameof(page1)))
newPage = page1;
if (parameters.ContainsKey(nameof(page2)))
newPage = page2;
parameters.ToList().ForEach(x => newPage = newPage.Replace("{" + x.Key + "}", x.Value));
return newPage;
}
Полученную строку с HTML-текстом записываем в свойство DocumentText WebBrowser-а.
И тут же получим бесконечный цикл перезагрузки страницы, поскольку установка этого свойства спровоцирует новый вызов OnBeforeNavigate2.
Временно отписаться от этого события не получится, поскольку вызывается оно откуда то из цикла обработки сообщений уже после того как установка DocumentText возвращает управление.
Т.о. необходимо всегда игнорировать каждый второй вызов обработчика, поскольку первое срабатывание это отправка формы в результате действий пользователя, которое обрабатывать нужно, а второе — отображение результата которое обрабатывать не нужно. Для простоты будем в начале обработчика OnBeforeNavigate2 переключать bool переменную.
ignore = !ignore;
if (ignore)
return;
И вот результат:
Это все что необходимо для минимального приложения. Но работать таким образом будет не все — за рамками осталось например получение данных о файлах для input type=«file», а также работа с XMLHttpRequest для корректной работы скриптов со всякими там ajax.
Исходный код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
namespace TestHtmlUI
{
internal sealed class MainForm : Form
{
private const string page1 = @"<!DOCTYPE html>
<html>
<head><meta http-equiv=""X-UA-Compatible"" content=""IE=11""></head>
<body>
<form method = ""post"" >
<input type=""text"" name=""TEXT1"" value=""Some text"" />
<input type=""submit"" value=""Open page 2"" name=""" + nameof(page2) + @""" />
</form>
</body>
</html>";
private const string page2 = @"<!DOCTYPE html>
<html>
<head><meta http-equiv=""X-UA-Compatible"" content=""IE=11""></head>
<body>
<div>{TEXT1}</div>
<form method=""post"">
<input type=""submit"" value=""Back to page 1"" name=""" + nameof(page1) + @""" />
</form>
</body>
</html>";
private delegate void BeforeNavigate2(object pDisp, string url, int Flags, string TargetFrameName, byte[] PostData, string Headers, ref bool Cancel);
private readonly WebBrowser webBrowser = new WebBrowser { Dock = DockStyle.Fill };
private bool ignore = true;
private MainForm()
{
StartPosition = FormStartPosition.CenterScreen;
Controls.Add(webBrowser);
Load += (sender, e) => ((dynamic)webBrowser.ActiveXInstance).BeforeNavigate2 += new BeforeNavigate2(OnBeforeNavigate2);
webBrowser.DocumentText = Handler(new Dictionary<string, string> { { nameof(page1), string.Empty } });
}
private void OnBeforeNavigate2(object pDisp, string url, int Flags, string TargetFrameName, byte[] PostData, string Headers, ref bool Cancel)
{
ignore = !ignore;
if (ignore)
return;
Cancel = true;
var parameters = (PostData == null ? string.Empty : Encoding.UTF8.GetString(PostData))
.Split('&')
.Select(x => x.Split('='))
.Where(x => x.Length == 2)
.ToDictionary(x => WebUtility.UrlDecode(x[0]), x => WebUtility.UrlDecode(x[1]));
webBrowser.DocumentText = Handler(parameters);
}
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
private static string Handler(IReadOnlyDictionary<string, string> parameters)
{
var newPage = "Not found";
if (parameters.ContainsKey(nameof(page1)))
newPage = page1;
if (parameters.ContainsKey(nameof(page2)))
newPage = page2;
// do dome usefull stuff here
parameters.ToList().ForEach(x => newPage = newPage.Replace("{" + x.Key + "}", x.Value));
return newPage;
}
}
}
Are you looking to develop a custom web browser using C# in a Windows Form application? In this guide, we will walk you through the process of building a simple web browser from scratch. By the end of this tutorial, you will have a functional web browser that you can enhance and customize further.
Setting Up the Windows Form Application
First, let’s create a new Windows Form application in Visual Studio. Follow these steps to get started:
- Open Visual Studio and create a new Windows Forms App (.NET Framework) project.
- Design the user interface by adding a
WebBrowser
control to the form. - Resize and position the
WebBrowser
control to fit the form as needed. - Customize the form with additional controls like back, forward, refresh buttons, and an address bar.
// Add a using directive for System.Windows.Forms
using System.Windows.Forms;
// Create a new instance of WebBrowser control
WebBrowser webBrowser = new WebBrowser()
{
Dock = DockStyle.Fill
};
// Add the WebBrowser control to the form
this.Controls.Add(webBrowser);
Handling Navigation and Browser Functions
Next, let’s implement basic browser functionalities such as navigation, refresh, and handling navigation events:
// Navigate to a specific URL
webBrowser.Navigate("https://www.example.com");
// Handle the Navigated event to update the address bar
webBrowser.Navigated += (sender, e) =>
{
addressBar.Text = webBrowser.Url.ToString();
};
// Implement functionality for back and forward buttons
backButton.Click += (sender, e) =>
{
if (webBrowser.CanGoBack)
{
webBrowser.GoBack();
}
};
forwardButton.Click += (sender, e) =>
{
if (webBrowser.CanGoForward)
{
webBrowser.GoForward();
}
};
// Implement refresh button functionality
refreshButton.Click += (sender, e) =>
{
webBrowser.Refresh();
};
Enhancing the Web Browser
To enhance your web browser further, consider adding features like bookmarks, history, tabbed browsing, and more. You can also customize the appearance and behavior of the browser to match your requirements.
Conclusion
Congratulations! You have successfully created a basic web browser using C# in a Windows Form application. Feel free to explore additional features and functionalities to make your web browser even more powerful. Happy coding!
This tutorial has provided you with a solid foundation for building a C# web browser in Windows Form. Experiment with different features and customization options to create a unique browsing experience tailored to your needs.
WebBrowser Control
WebBrowser control allows developers to build Web browsing
capability within Windows Forms applications. In this article, I will
demonstrate how to use the WebBrowser control in a Windows Forms application
using C# and Visual Studio 2010.
In 2001, I published an article Web Browser in C# and VB.NET that showed how to use the WebBrowser ActiveX control in a Windows Forms 1.0/1.1 application. Well, things have changed since then.
This article is written using Visual Studio 2010 and Windows Forms 4. If you do not
have Visual Studio 2010, you may use Visual C# 2010 Express which is free to
download from the MSDN website.
Creating a WebBrowser
Create
a Windows Forms application using Visual Studio 2010 or Visual C# 2010 Express.
In
this application, I am going to add a ToolStrip and WebBrowser control to
the form. In my ToolStrip control, I add a Label, a TextBox, and a few Button
controls with a few separators.
By
the time we are done with the application, the final user interface will look
like Figure 1.
Figure 1
After
your Toolbar looks like Figure 1, drag a WebBrowser control from Toolbox to the
Form and resize and dock the control the way you like on the Form. I dock the
WebBrowser control at the bottom of the window.
Figure
2
In the next step, I am going to set default properties of the WebBrowser control.
To
do so, right-click on the WebBrowser control, and select Properties. This action
launches the Properties window. Feel free to set any properties you like. The Url
property represents the web page a WebBrowser displays. In Figure 3, I set http://www.c-sharpcorner.com as the default page to display in the
browser.
Figure
3
Navigation
The WebBrowser class in code behind is associated with the
WebBrowser control. So when you drag and drop a WebBrowser control to the Form,
a WebBrowser class instance is created in the code behind.
The Navigate method of the WebBrowser class is used to open a URL
in the WebBrowser.
- webBrowser1.Navigate(new Uri(url));
The following code snippet is code written on the Go button click
event handler where I open a URL in the WebBrowser using the Navigate method.
- private void GoButton_Click(object sender, EventArgs e)
- {
- if (String.IsNullOrEmpty(UrlTextBox.Text) || UrlTextBox.Text.Equals(«about:blank»))
- {
- MessageBox.Show(«Enter a valid URL.»);
- UrlTextBox.Focus();
- return;
- }
- OpenURLInBrowser(UrlTextBox.Text);
- }
- private void OpenURLInBrowser(string url)
- {
- if (!url.StartsWith(«http://») && !url.StartsWith(«https://»))
- {
- url = «http://» + url;
- }
- try
- {
- webBrowser1.Navigate(new Uri(url));
- }
- catch (System.UriFormatException)
- {
- return;
- }
- }
WebBrowser control also has built-in browser methods to go home, forward,
backward, refresh, save, print and others.
The following code snippet shows how to use GoForeward, GoBack,
GoHome, and Refresh methods.
- private void HomeButton_Click(object sender, EventArgs e)
- {
- webBrowser1.GoHome();
- }
- private void BackButton_Click(object sender, EventArgs e)
- {
- if (webBrowser1.CanGoBack)
- webBrowser1.GoBack();
- }
- private void NextButton_Click(object sender, EventArgs e)
- {
- if (webBrowser1.CanGoForward)
- webBrowser1.GoForward();
- }
- private void RefreshButton_Click(object sender, EventArgs e)
- {
- webBrowser1.Refresh();
- }
The ShowSaveAsDialog, ShowPrintDialog, ShowPrintPreviewDialog, and
ShowProperties methods are used to display SaveAs diaog, Print dialog,
PrintPreview dialog, and Properties dialog respectively. The following code
snippet shows how to call these methods.
- private void SaveButton_Click(object sender, EventArgs e)
- {
- webBrowser1.ShowSaveAsDialog();
- }
- private void PrintPreviewButton_Click(object sender, EventArgs e)
- {
- webBrowser1.ShowPrintPreviewDialog();
- }
- private void PrintButton_Click(object sender, EventArgs e)
- {
- webBrowser1.ShowPrintDialog();
- }
- private void PropertiesButton_Click(object sender, EventArgs e)
- {
- webBrowser1.ShowPropertiesDialog();
- }
Summary
In this article, I discussed how to use a WebBrowser control in
Windows Forms at design-time as well as run-time. After that, we saw how to use
various properties and methods of the WebBrowser control.
Recommended Readings
Here are some more articles on the WebBrowser control including different versions of Visual Studio and Windows Forms.
- Web Browser control in WPF
- Web Browser in C#
- Web Browser in C#
- How to use Web Browser control in Visual Studio 2005
- Web Browser in C# and VB.NET
- WebBrowser Control in WPF
- Windows Forms WebBrowser Control
- Web-Enabled C# Application