Использование элемента управления Windows Forms WebBrowser для отображения веб-страниц во вкладках



1.Введение


Часто при разработке приложений под Windows необходимо отобразить в нем веб-страницы. Например, это может быть справка в формате HTML или веб-кабинет пользователя на сайте программы. Для этих целей Net Framework предоставляет элемент управления WebBrowser. Он существует как для Windows Forms, так и для WPF. Поскольку принципы их работы схожи, технология Windows Forms все еще популярна, и встроить элемент управления WinForms в WPF-приложение легко, мы рассмотрим использование данного элемента в приложении Windows Forms.

 

Во всех современных браузерах есть функция отображения страниц во вкладках: это делает работу с веб-сайтами более удобной. Однако, при использовании элемента WebBrowser, эта функция недоступна, и пункт контекстного меню «Открыть в новой вкладке» при нажатии по ссылке подсвечивается серым. Но это не проблема, поскольку эту функцию можно реализовать самостоятельно, что и рассматривается в данной статье. Мы будем использовать среду разработки Visual Studio 2010 Express и язык программирования C#.

 

2. Принципы реализации


Для реализации вкладок мы будем размещать несколько элементов WebBrowser на странице (в элементе Panel). В каждый момент будет видим только один элемент WebBrowser (соответствующий активной вкладке). Для отображения заголовков вкладок сы будем использовать элемент FlowLayoutPanel – контейнер WinForms, компонующий элементы в строку. Для каждой вкладки в него будет добавляться дочерний FlowLayoutPanel, содержащий две кнопки: перехода на данную вкладку (отображающая заголовок страницы) и закрытия вкладки (отображающая знак Х). Соответствие между браузерами их вкладками реализуется с помощью свойства Tag, которое есть у любого элемента.

 

Переход на новую вкладку будет осуществляться, когда пользователь нажмет правой кнопкой по ссылке и в контекстном меню выберет пункт «Открыть в новом окне». (Сама функциональность этого пункта довольно бесполезна при встраивании браузера в свое приложение, поэтому можно от нее избавиться.) Измененный обработчик события будет получать адрес активной ссылки (атрибут HREF активного элемента WebBrowser.Document.ActiveElement), открывать его в новой вкладке и отменять стандартную обработку события.

 

3. Размещение элементов на форме


В Visual Studio создайте проект Windows Forms Application. Откройте конструктор созданной по умолчанию формы Form1. Разместите на форме элементы Panel и FlowLayoutPanel согласно рисунку 1. Дополнительно на форме разместите элементы управления, который позволят пользователю открыть необходимый ресурс (например, поле ввода URL и кнопка перехода).

 




Рисунок 1 – Размещение элементов на форме

 

Установите параметры Anchor для элементов, чтобы обеспечить их правильную реацию на изменение размера формы: Top/Left/Right для FlowLayoutPanel, Top/Bottom/Left/Right для Panel. Далее переходим к написанию кода.

 

4. Написание кода


Добавим к проекту новый класс BrowserTab, представляющий собой описание структуры данных отдельной вкладки. Добавьте в класс следующий код:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
 
namespace WebBrouser
{
    //вкладка браузера
    public class BrowserTab
    {
        public int num;//номер вкладки
        public WebBrowser browser;//элемент управления Браузер
        public FlowLayoutPanel title_panel;//панель вкладки
        public Button title_button;//кнопка перехода на данную вкладку
        public Button close_button;//кнопка закрытия данной вкладки
    }
}

 

В класс главной формы добавим следующие переменные:

 

BrowserTab _CurrentTab=null;//активная на данный момент вкладка

WebBrowser _CurrentBrowser=null;//активный на данный момент элемент-браузер

List<BrowserTab> _BrowserTabs = new List<BrowserTab>();//все вкладки

 

Добавим метод, создающий новую вкладку и реализующий добавление необходимых элементов управления на форму:

 

public BrowserTab CreateNewTab(string page)//создание новой вкладки
        {
            BrowserTab tab = new BrowserTab();
 
            /*Получение номера новой вкладки*/
            int num = 0;
            foreach (BrowserTab x in _BrowserTabs)
            {
                if (x.num > num) num = x.num;
            }
            tab.num = num+1;
 
            /*Создание компонентов...*/
            tab.browser = new WebBrowser();
            tab.browser.Dock = DockStyle.Fill;//элемент заполняет родительский элемент
            tab.browser.NewWindow += webBrowser_NewWindow;
//обработчик события "Открыть в новом окне"
            tab.browser.DocumentCompleted += webBrowser_DocumentCompleted;
            tab.browser.Visible = false;//элемент изначально невидим
            tab.browser.Tag = tab;//вкладка, с которой связан данный браузер
            tab.title_panel = new FlowLayoutPanel();//заголовок вкладки
            tab.title_panel.BorderStyle = BorderStyle.Fixed3D;//объемная граница
            tab.title_panel.AutoSize = true;
//размер элемента соответствует размеру его содержимого
 
            tab.title_button = new Button();//кнопка перехода на данную вкладку
            tab.title_button.AutoSize = true;//размер элемента соответствует размеру его содержимого
            tab.title_button.Text = "Новая вкладка " + num.ToString();
            tab.title_button.Tag = tab;
            tab.title_button.Click += Tab_Activate_Click;//обработчик события перехода на эту вкладку
            tab.title_panel.Controls.Add(tab.title_button);
 
            tab.close_button = new Button();//кнопка закрытия
            tab.close_button.AutoSize = true;//размер элемента соответствует размеру его содержимого
            tab.close_button.Text = "X";
            tab.close_button.Width = 1;
            tab.close_button.Tag = tab;
            tab.close_button.Click += Tab_Close_Click;//обработчик события для закрытия вкладки
            tab.title_panel.Controls.Add(tab.close_button);
 
            //добавляем созданные компоненты на форму
            flowLayoutPanel1.Controls.Add(tab.title_panel);
            panel1.Controls.Add(tab.browser);
            _BrowserTabs.Add(tab);
 
            if (page != "") tab.browser.Navigate(page);//если есть URL, переходим по нему
            return tab;
        }

 

Добавим реализации некоторых вспомогательных методов:

 

public void SetTitle(BrowserTab tab, string title)
        {
            tab.title_button.Text = title;//изменение заголовка вкладки
        }
 
        public void CloseTab(BrowserTab tab)//закрытие вкладки
        {
            //если вкладка в данный момент видима,
            //активной будет сделана предыдущая вкладка
            if (tab.browser.Visible == true )
            {
                _CurrentTab = null;
                _CurrentBrowser = null;
                if (_BrowserTabs.Count > 1)
                {
                    int index = _BrowserTabs.IndexOf(tab);
                    index--;
                    if (index < 0) index++;
                    this.ActivateTab(_BrowserTabs[index]);
                }
            }
 
            //удаление элементов
            panel1.Controls.Remove(tab.browser);
            flowLayoutPanel1.Controls.Remove(tab.title_panel);
            _BrowserTabs.Remove(tab);
            tab.browser.Dispose();
            tab.close_button.Dispose();
            tab.title_button.Dispose();
            tab.title_panel.Dispose();           
        }
 
        public void ActivateTab(BrowserTab tab)//активация вкладки
        {
            foreach (BrowserTab x in _BrowserTabs)
            {
                x.title_button.ForeColor = Color.Black;
                x.browser.Visible = false;
            }
 
            //делаем видимой активную вкладку
            //и выделяем ее заголовок синим цветом
            tab.title_button.ForeColor = Color.Blue;
            tab.browser.Visible = true;
            _CurrentBrowser = tab.browser;
            _CurrentTab = tab;
            if (_CurrentBrowser.Url != null)
            {
                tbAddress.Text = _CurrentBrowser.Url.ToString();
            }
            sCurrentUrl.Text = tbAddress.Text;
        }
 

 

Добавим методы-обработчики событий для наших динамически создаваемых элементов WebBrowser:

 

void Tab_Close_Click(object sender, EventArgs e)//обработчик события закрытия вкладки
        {
            CloseTab((BrowserTab)(((Button)sender).Tag));
        }
 
void Tab_Activate_Click(object sender, EventArgs e)//обработчик события активации вкладки
        {
            ActivateTab((BrowserTab)(((Button)sender).Tag));
        }      
 
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            sCurrentState.Text = "Загружено";
            sCurrentUrl.Text = _CurrentBrowser.Url.ToString();
            string title = ((WebBrowser)sender).DocumentTitle;
            SetTitle((BrowserTab)((WebBrowser)sender).Tag, title);
        }
 
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {           
            sCurrentState.Text = "Загрузка...";
            sCurrentUrl.Text = _CurrentBrowser.Url.ToString();           
        }
 
void webBrowser_NewWindow(object sender, CancelEventArgs e)//обработчик открытия элемента в новом окне
        {
            e.Cancel = true;
            CreateNewTab(((WebBrowser)sender).Document.ActiveElement.GetAttribute("href"));                       
        }

 

5. Результат


Вид работающего приложения представлен на рисунке 2.

 


Рисунок 2 – Вид работающего приложения

 


При выборе пункта «Открыть в новом окне» откроется новая вкладка (рисунок 3).

 
 



Рисунок 3 – Вторая вкладка

 

6.Заключение


В данной статье мы рассмотрели создание графического интерфейса для просмотра веб-страниц в нескольких вкладках с помощью компонента WebBrowser. Данный прием будет полезен для создания удобной справочной системы в вашем приложении или для взаимодействия со страницами вашего веб-сайта. Полный код проекта можно загрузить по адресу http://smallsoft.h16.ru/files/prog/webbrowser.zip

 

На последок хочу добавить, что компонент WebBrowser использует движок Internet Explorer, который может выводить много сообщений об ошибках сценариев на некоторых сайтах. Для отключения этих сообщений можно использовать свойство ScriptErrorsSupressed.

 

Автор: Свиткин В.Г.


 

 

 

 

 

 

Комментариев нет:

Отправить комментарий