I have a TABLE
Element in the current Document of a WebBrowser control.
I want to be able to color a Cell when my cursor is on it, when I press the A
Key
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
htmlDocument1 = WebBrowser1.Document
AddHandler htmlDocument1.MouseOver, AddressOf Me.gettd
End Sub
Public Sub gettd(ByVal sender As Object, ByVal e As System.Windows.Forms.HtmlElementEventArgs)
Dim theElementCollection As HtmlElementCollection
theElementCollection = WebBrowser1.Document.GetElementsByTagName("td")
For Each curElement As HtmlElement In theElementCollection
e.ToElement.Style = "background-color: orange;"
Next
End Sub
Setting KeyPreview = True
:
Public Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.A Then
...
end if
End Sub
How else can I achieve this?
A few changes are required:
The DocumentCompleted
event can be used to add handlers to other events, but you have to remember that this event is raised multiple times per URI navigated: you're adding a multitude of handlers to the MouseOver
event.
It's simpler, in this case, to add a handler when the URI has been Navigated and remove it when we're Navigating to another.
Also, read the notes here: How to get an HtmlElement value inside Frames/IFrames?
Instead of parsing the whole collection of Elements in the Document, we can simply use the Document.GetElementFromPoint() method, passing the e.ClientMousePosition value provided by the MouseOver
or MouseMove
events as the current Point position.
The Form's KeyDown event cannot be used to trap keys pressed - even with KeyPreview set to True
- when other controls capture the input. You can get that key press overriding the Form's ProcessCmdKey, since it's called when messages are pre-processed.
Always check for null
before accessing a HtmlElement or its properties. E.g., string properties never initialized are null
(Nothing
), not String.Empty
.
Add this code to a Form, then navigate to a Html Page:
webBrowser1.Navigate("[Some URI]")
I've added a toggle function, to set the current Cell's Style to a background-color
value when Keys.A
is pressed and set it back when it's pressed again. Here, hard-coded to white
, but you can add some logic to save the previous style, if required.
Public Class FormBrowser
Private trackedElement As HtmlElement = Nothing
Private elementColorOrange As String = "background-color: orange;"
Private elementColorWhite As String = "background-color: white;"
Private Sub webBrowser1_Navigating(sender As Object, e As WebBrowserNavigatingEventArgs) Handles webBrowser1.Navigating
If webBrowser1.Document Is Nothing Then Return
RemoveHandler webBrowser1.Document.MouseOver, AddressOf OnBrowserMouseOver
End Sub
Private Sub webBrowser1_Navigated(sender As Object, e As WebBrowserNavigatedEventArgs) Handles webBrowser1.Navigated
AddHandler webBrowser1.Document.MouseOver, AddressOf OnBrowserMouseOver
End Sub
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If keyData = Keys.A Then
If trackedElement IsNot Nothing AndAlso trackedElement.TagName = "TD" Then
Dim currentStyle As String = trackedElement.Style & ""
trackedElement.Style = If(currentStyle.Contains(elementColorOrange), elementColorWhite, elementColorOrange)
Return True
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class
Private Sub OnBrowserMouseOver(sender As Object, e As HtmlElementEventArgs)
Dim doc = DirectCast(sender, WebBrowser).Document
If doc Is Nothing Then Return
trackedElement = doc.GetElementFromPoint(e.ClientMousePosition)
txtElmName.Text = trackedElement?.OuterHtml
txtElmValue.Text = trackedElement?.InnerHtml
End Sub
This is how it works: