I am capturing click coordinates within a PictureBox but I want to achieve the same thing with a WebBrowser. After some research I found out that it is not possible to subscribe to the Mouse Click
event of a WebBrowser control.
What are the possible ways to capture the clicks? Is there a sort of element which would allow me to navigate through the page but still capture the click?
I tried to create a transparent panel but transparent color doesn't mean see through as I see and when the element is in the back also doesn't capture the click, being able to capture the clicks with panel being behind the WebBrowser would also work.
PictureBox code:
private void uploadedPNG_MouseClick(object sender, MouseEventArgs e)
{
if(uploadedPNG.Image != null && !string.IsNullOrEmpty(deviceHeight.Text) && !string.IsNullOrEmpty(deviceWidth.Text))
{
mouseX = e.X;
mouseY = e.Y;
targetHeight = Int32.Parse(deviceHeight.Text);
targetWidth = Int32.Parse(deviceWidth.Text);
int outPutWidth = (mouseX * targetWidth) / uploadedPNG.Width;
int outPutHeight = (mouseY * targetHeight) / uploadedPNG.Height;
ConsoleText.Text = "Clicked X coordinate " + outPutWidth + " Clicked Y coordinate " + outPutHeight;
}
}
The WebBrowser itself doesn't provide Mouse Click coordinates: you're not actually clicking on the Control client area, you're clicking on the content of the HtmlDocument.
You can use the HtmlDocument.Click or HtmlDocument.MouseDown events to retrieve the Mouse pointer coordinates on an initialized HtmlDocument.
Note:
The HtmlElementEventArgs object returns the Mouse coordinates in both absolute coordinates (the whole Document area), in e.ClientMousePosition and relative to the clicked HtmlElement
, in e.OffsetMousePosition.
This can be tricky, because you need to subscribe to the Click
event when the current HtmlDocument is already created: you cannot subscribe to the event of the default Document object:
i.e., subscribing to the event in Form.Load
with:
webBrowser1.Document.Click += (obj, evt) => { /*Do something */ };
will not accomplish anything. The event will never be raised: the Document is null
thus, of course, it's not referency any current/active HtmlDocument.
An HtmlDocument
is ready when the WebBrowser.DocumentCompleted event is raised and its ReadyState is set to WebBrowserReadyState.Complete
.
You can subscribe to the Document.Click
event when the Document is fully loaded, then remove the event before the WebBrowser navigates to a new page, creating a new document.
Also, the DocumentCompleted
event may be raised multiple times for a single HTML
page, so you need to be sure that you don't subscribe to the same event multiple times:
Note:
A HtmlDocument
may contain more than one Frame/IFrame
and each Frame
may have its own HtmlDocument
; IFrames
have one each for sure. Refer to the notes in this question for more informations on this matter:
How to get an HtmlElement value inside Frames/IFrames?
An example:
bool WebBrowserDocumentEventSet = false;
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = (sender as WebBrowser);
if (wb.ReadyState == WebBrowserReadyState.Complete && WebBrowserDocumentEventSet == false)
{
WebBrowserDocumentEventSet = true;
wb.Document.MouseDown += this.OnHtmlDocumentClick;
}
}
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
(sender as WebBrowser).Document.MouseDown -= this.OnHtmlDocumentClick;
WebBrowserDocumentEventSet = false;
}
protected void OnHtmlDocumentClick(object sender, HtmlElementEventArgs e)
{
Console.WriteLine(e.ClientMousePosition);
}