4

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;
    }
}
Jimi
  • 29,621
  • 8
  • 43
  • 61
  • I dont quite understand the question, Do you want the coordinates from the winform - PictureBox control ? – karthickj25 Jan 17 '19 at 08:47
  • I am able to capture the coordinates from PictureBox or Panel, but I need to capture coordinates in WebBrowser –  Jan 17 '19 at 08:49
  • 1
    I haven't tried it, but you may try to override `WndProc` method of the form that hosts your web browser, capture [wm_lbuttondown](https://learn.microsoft.com/en-us/windows/desktop/inputdev/wm-lbuttondown) and raise your event before it goes to the WebBrowser. – Nick Jan 17 '19 at 08:56
  • do you need the mouse position relative to screen or within the bounds of the webpage inside the control ? – karthickj25 Jan 17 '19 at 09:06
  • Within the bounds of the webpage inside the control –  Jan 17 '19 at 09:08
  • @Nick, sorry I am quite a beginner with c# and I am not even sure where to define the "#define WM_LBUTTONDOWN 0x0201" –  Jan 17 '19 at 09:09
  • @PoYo That's c++, you can't `define` it like this. it's just a constant – slow Jan 17 '19 at 09:16
  • @sLw excuse my ignorance :) –  Jan 17 '19 at 09:21

1 Answers1

4

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 HTMLpage, 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);
}
Jimi
  • 29,621
  • 8
  • 43
  • 61
  • Thank you a lot, your example solves my problem partly, but I still don't know how to get the coordinates before the page navigates, purpose my application is to generate coordinates to be used in automated test, and within the web application I am testing there are multiple pages and i need to record this coordinates too –  Jan 17 '19 at 09:39
  • I'm not really sure what you mean with *get the coordinates before the page navigates*. The coordinates of what? There's nothing on the page until the document is loaded. Can you provide an example of the procedure you're referring to? Btw, if you're referring to the Page Frames, each Frame has its own Document. You can subscribe to the Click event of each Frame Document, if this is what you want. [See the notes here](https://stackoverflow.com/a/53218064/7444103) – Jimi Jan 17 '19 at 09:44
  • Coordinates are logged if I am not clicking to link, and when I click to a button, which is linked to another page within the application, coordinates are not logged. –  Jan 17 '19 at 09:51
  • The event is raised no matter where the Mouse performs the click, a blank point on the page or any kind of link. If you want some help in resolving your problem, you need to clearly describe your scenario , what is that you want ot achieve and what is not working as you want it to. Update your question with these details, possibly, so I can provide some meaningful suggestions. For example, do you have more than one Frame on those pages? IFrames, maybe? – Jimi Jan 17 '19 at 10:00
  • Sorry, seems to work now, somehow click event was behaving badly in my web application, i replaced the Document.Click with Document.MouseDown in your example, everything worked out perfectly. Thank you a lot again. –  Jan 17 '19 at 10:13
  • Well, I'm glad you got it to work. I'll update the answer to reflect this finding. It may depend on the underlying scripts that handle the Click event on the Html Elements. I'll make some tests. – Jimi Jan 17 '19 at 10:24
  • 1
    I guess I know the reason now, I am removing event handlers in most of the cases using .off() in JS because my web application also aims touch devices and I had some issues which I solved with .off(), mainly problem with navigation buttons. And that was exactly where click events were not captured. –  Jan 18 '19 at 08:21
  • Well, if that's the actual condition that causes the Click event to end up in a limbo, good to know. I will point to this question if the issue bubbles up again. – Jimi Jan 18 '19 at 10:20