msvb - Visual Basic - авторский сайт
 
Главная
Документы
Обзоры программ
Гостевая книга
 
Материалы раздела:

Использование WebBrowser и MSHTML в VB. Часть 2

Перехват и обработка событий.

Способы загрузки содержания обсуждались в предыдущей статье. Здесь речь пойдёт о различных способах обработки событий html-документа. Использование vbscript и javascript не рассматривается по идеологическим соображениям.

Событие BefoNavigate

Самый простой способ создать реакцию на действие пользователя - использовать событие BefoNavigate элемента управления WebBrowser. Оно возникает перед началом загрузки нового документа, например, при нажатии ссылки в текущем документе. Для того, чтобы определить какой из пунктов выбран - анализируется текст ссылки. В данном примере есть ещё одна особенность. Для удаления полосы прокрутки используется строка 'body {overflow-y: visible;}'.

Private Sub Form_Load()
    'загрузка документа
    WebBrowser1.Navigate "about:" & _
    "<html> <head> <style type=""text/css""> body {overflow-y: vi" & _
    "sible;} a.item {color: #003DB2; font-family: Verdana, Arial," & _
    " Helvetica, sans-serif; text-decoration: none;} a.item:link," & _
    " a.item:visited, a.item:active {background-color: #B9D0F1;} " & _
    "a.item:hover {background-color: #DDECFE;} </style> </head> <" & _
    "body> <a href=""id1"" class=""item"">пункт 1</a><br> <a href" & _
    "=""id2"" class=""item"">пункт 2</a><br> <a href=""id3"" clas" & _
    "s=""item"">пункт 3</a> </body> </html>"
End Sub

Private Sub WebBrowser1_BeforeNavigate2(ByVal pDisp As Object, _
    URL As Variant, Flags As Variant, TargetFrameName As Variant, _
    PostData As Variant, Headers As Variant, Cancel As Boolean)

    If Mid$(URL, Len(URL) - 2, 2) = "id" Then
    'проверка URL
        MsgBox "Выбран пункт " & Right$(URL, 1)
        'отмена обработки события
        Cancel = True
    End If
End Sub

У данного метода есть несколько преимуществ:

  • простота реализации.
  • можно использовать стили для автоматического оформления элемента управления

Недостаток один, но большой: можно перехватить только два события - нажатие enter или клик мышкой. Для обработки остальных событий следует воспользоваться MSHTML

Получение событий документа

Чтобы это стало возможным необходимо сделать следующее:

  • добавить в Referens проекта ссылку на библиотеку MSHTML
  • объявить в классе модуля WithEvents html документ
  • инициализировать его документом, полученным от элемента WebBrowser

Теперь необходимо выбрать событие и добавить код, его обрабатывающий.

Для того чтобы получить элемент документа, к которому относится событие необходимо обратиться к объекту Event следующим образом: 'mHTMLDocument.parentWindow.Event.srcElement'.

После этого необходимо определить необходимость и способ обработки события для данного элемента. Обычно, количество элементов html - документа гораздо больше, чем элементов управления на обычной форме. Можно предложить несколько путей для выбора нужного элемента.

  • проверка уникального идентификатора элемента. Удобно пользоваться при небольшом количестве таких элементов. При динамическом формировании содержания, надо очень внимательно следить, чтобы ID элементов были уникальными.
  • проверка названия тега элемента. Этим способом можно обрабатывать определённый тип элементов.
  • проверка наличия и значения атрибута. Html допускает наличие у элементов произвольных атрибутов. Этим можно воспользоваться для создания новых свойств элементов, определяющих необходимость и способ обработки событий. Для того чтобы определить наличие атрибута у элемента используется метод 'getAttribute'.

Если необходимо обработать события для группы элементов - можно воспользоваться свойством 'parentElement', возвращающим элемент - предок. Следующий пример демонстрирует упрощённый способ обработки событий.

'References: Microsoft HTML Object Library
'Controls: Microsoft Internet Controls
'добавить на форму WebBrowser с именем WebBrowser1

Private WithEvents mHTMLDocument As MSHTML.HTMLDocument

Private Sub Form_Load()
    Dim strBlankFile As String
    strBlankFile = "about:" & _
    "<input id=""txt1"" type=""text"" size=""20"" value=""текст""/>" & _
    "<input id=""cmd1"" type=""submit"" value=""пуск""/>"
    'загрузка документа
    WebBrowser1.Navigate strBlankFile
    While WebBrowser1.Document Is Nothing
        DoEvents
    Wend
    'присваиваем html документ
    Set mHTMLDocument = WebBrowser1.Document
End Sub

Private Function mHTMLDocument_onclick() As Boolean
    'обработка событий только для элемента с идентификатором 'cmd1'
    If mHTMLDocument.parentWindow.Event.srcElement.Id = "cmd1" Then
        MsgBox mHTMLDocument.getElementById("txt1").Value
    End If
End Function

Этот пример - более сложен. Демонстрирует загрузку html из переменной, использование объекта 'Event', нестандартных атрибутов и изменение содержания html документа во время работы программы.

'References: Microsoft HTML Object Library
'Controls: Microsoft Internet Controls
'добавить на форму WebBrowser с именем WebBrowser1

Private WithEvents mHTMLDocument As MSHTML.HTMLDocument

Private Sub Form_Load()
    Dim mStr As String
    Dim mDoc As MSHTML.IHTMLDocument

    'загрузка простого документа
    WebBrowser1.Navigate "res://mshtml.dll/blank.htm"
    While WebBrowser1.Document Is Nothing
    'ждём создания документа
        DoEvents
    Wend
    Set mDoc = WebBrowser1.Document
    mStr = "<html><body>" & _
           "  <head><style type=""text/css"">" & _
           "    body {overflow-y: visible;}" & _
           "    span {color: #003DB2;}" & _
           "    li   {cursor: hand;}" & _
           "  </style></head>" & _
           "  <ul>" & _
           "    <li id=""1"" sel=""1"">пункт <span>1</span></li>" & _
           "    <li id=""2"" sel=""0"">пункт <span>2</span> " & _
           "    (не активен)</li>" & _
           "    <li id=""3"" sel=""1"">пункт <span>3</span></li>" & _
           "  </ul>" & _
           "  <div id=""txtout"">нужно кликнуть по списку</div>" & _
           "</body></html>"
    'меняем содержание всего документа
    mDoc.Write mStr
    Set mDoc = Nothing

    'присваиваем html документ
    'для обработки событий
    Set mHTMLDocument = WebBrowser1.Document
End Sub

'нажатие кнопки мыши
Private Sub mHTMLDocument_onmousedown()
    Dim objElement As MSHTML.IHTMLElement
    Dim mDiv As MSHTML.HTMLDivElement
    'получаем элемент, в который будем выводить сообщения
    'по его идентификатору
    Set mDiv = mHTMLDocument.getElementById("txtout")

    'если нажата правая кнопка - отмена события
    If mHTMLDocument.parentWindow.Event.button = 2 Then
        mHTMLDocument.parentWindow.Event.returnValue = False
        Exit Sub
    End If

    'получить элемент, для которого обрабатывается событие
    Set objElement = mHTMLDocument.parentWindow.Event.srcElement

    'получить элемент, имеющий атрибут "Sel"
    Do While IsNull(objElement.getAttribute("Sel")) = True
        Set objElement = objElement.parentElement
        'поднялись до вершины иерархии, но такого элемента
        'не встретили - выводим сообщение и выход из процедуры
        If objElement Is Nothing = True Then
            mDiv.innerHTML = "нужно кликнуть по списку"
            Exit Sub
        End If
    Loop

    'проверяем значение атрибута
    If objElement.Sel = "1" Then
        mDiv.innerHTML = "выбран пункт " & objElement.Id
    Else
        mDiv.innerHTML = "пункт " & objElement.Id & " не активен"
    End If
End Sub

К недостаткам данного способа следует отнести невозможность обработки ряда событий, характерных для некоторых элементов. Например, событие 'onchange' для поля со списком или 'onpropertychange' для строки ввода. В этом случае можно воспользоваться следующим способом.

Обработка событий на уровне элемента

Способ аналогичен предыдущему, но WithEvents объявляется не документ, а конкретный элемент

'References: Microsoft HTML Object Library
'Controls: Microsoft Internet Controls
'добавить на форму WebBrowser с именем WebBrowser1

Private WithEvents mInputElement As MSHTML.HTMLInputElement

Private Sub Form_Load()
    Dim strBlankFile As String
    Dim mHTMLDocument As MSHTML.IHTMLDocument
    strBlankFile = "about:."
    
    'загрузка документа
    WebBrowser1.Navigate strBlankFile
    While WebBrowser1.Document Is Nothing
        DoEvents
    Wend
    'присваиваем html документ
    Set mHTMLDocument = WebBrowser1.Document
    mHTMLDocument.Write _
    "<input id=""txt1"" type=""text"" size=""20"" value=""""/>"
    'получаем элемент, используя коллекцию 'All'
    Set mInputElement = mHTMLDocument.All.txt1
    mInputElement.Value = "измените текст"
    'установка фокуса
    mInputElement.setActive
End Sub

Private Sub mInputElement_onpropertychange()
    Me.Caption = mInputElement.Value
End Sub 

Обработка определённого события элемента

Элементы html документа имеют свойства, соответствующие событиям, которые они регистрируют. В скиптовых языках такому свойству может быть назначено имя функции, и она будет вызвана при возникновении соответствующего события. В Visual Basic этим свойствам может быть присвоен класс и вызываться будет заданная по умолчанию процедура. Этот способ описан статье MSDN Handling Events in Visual Basic Applications.

В примере, также демонстрируется ещё один способ загрузки html. Сначала загружается пустой документ из ресурсов файла 'mshtml.dll'. Это и есть страница 'about.blank'. Дальнейшая работа происходит в событии 'DocumentComplete' которое возникает по окончании загрузки. Метод 'innerHTML' изменяет содержание, записывая html код в тело документа. При таком подходе подключение библиотеки mshtml не требуется. Обратите внимание на ещё один способ избавления от вертикальной полосы прокрутки: 'body.Style.overflow = "hidden"'.

код формы:

'Controls: Microsoft Internet Controls
'добавить на форму WebBrowser с именем WebBrowser1

Private Sub Form_Load()
    'загрузка документа 'about:blank' из файла ресурсов
    WebBrowser1.Navigate "res://mshtml.dll/blank.htm"
End Sub

Private Sub WebBrowser1_DocumentComplete _
        (ByVal pDisp As Object, URL As Variant)
    Dim cHtmlEvent As New clsHtmlEvent
    With WebBrowser1.Document
        'присваиваем html документ
        .body.innerHTML = _
        "<input id=""cmd1"" type=""submit"" value=""пуск""/>"
        'убираем полосу прокрутки
        .body.Style.overflow = "hidden"
        'задаём обработку события
        .All("cmd1").onclick = cHtmlEvent
    End With
End Sub

код класса 'clsHtmlEvent'

'класс clsHtmlEvent

Public Sub CmdClick()
    'эта процедура должна быть процедурой по умолчанию
    'для этого: в меню 'Tools' пункт 'Procedure Attributes'
    'нажать кнопку 'Advanced >>'
    'в списке 'Procedure ID' выбрать 'Default' и нажать 'OK'
    MsgBox "клик по кнопке"
End Sub

В следующей статье речь пойдёт о создании интерфейса программ и использовании скинов.



 
Copyright © 2004—2005 marvan
msvb@yandex.ru
Hosted by uCoz