c# / vb.net webbrowser get htmlelement position - c#

I am trying to get position of html elements in a .net's webbrowser control and failing,
i need the exact position of the element relative to the whole document or the webbrowser control to be able to send a mouse click using SendMessage() P/Invoke ..
I have tried the solution from here but it didn't work:
getting absolute position of HTML element in webbrowser control with C#
I am guessing that is because the page relies on very complex ajax and css.
the function "WebBrowser1.Document.GetElementFromPoint()" works just fine in getting the accurate html element, i just need the opposite of it.
other wise, should i just keep on searching using "GetElementFromPoint()" until getting the correct element ???
Thanks.

As I am unable to comment on your question, I'll go for making an "answer", even though it won't be much of one...
What's wrong with clicking the element via JavaScript / InvokeMethod?
You could also modify the CSS for the element, making it cover the
whole of the viewport, allowing you to click anywhere within the web
browser control's viewport.
If you were to post reasons why the solution from your link was unable to work, then it would be easier possible to give you a solution to the problem.

You may get the same exact behaviour by simply doing something like this:
public void ClickHtmlElement(WebBrowser o, string htmlElementId)
{
const string mask = #"javascript:void(document.getElementById('{0}').click())";
string url = string.Format(mask, htmlElementId);
o.Navigate(url);
}

I have this exact same issue. Invoke, .domelement.click(), .click etc... doesn't work, sendmessage does work, but that requires the exact X,Y position.
The only solution I have at the moment is horrible. Basically using GetElementFromPoint(), but instead of going point by point, you can use a step of the width and height of your element.
So if your element is 500 pixels high and 500 pixels wide, then you can search point 0,500,1000,1500 etc.
I've found some jQuery code that shows how complex it actually is to get the correct X,Y position:
https://github.com/jquery/jquery/blob/master/src/offset.js
I can't believe there isn't an easier way :-(

Related

Get HTML display area (viewport) offset to 0/0 and zoom of IE window using .NET/C# and SHDocVw.InternetExplorer

THIS IS NOT A HTML / JAVASCRIPT / CSS question!
Check out these images:
I need to get the HTML display area (aka viewport) offset to the 0/0 of the IE window.
I am targeting Microsoft Internet Explorer 11.
I am using C# with SHDocVw.InternetExplorer library to access/control the IE.
What I actually want to do is to trigger double-click events
similar to IHTMLElement.click(), just a doubleClick()
calling IHTMLElement.click() multiple times does not work
I tried to solve it WITHOUT actually clicking:
How to make SHDocVw.InternetExplorer fire events that get caught with JS addEventListener?
but that has not received any answers yet
So right now I'm controlling the mouse to trigger certain events, calling [DllImport("user32.dll")] public static extern bool GetCursorPos(out PointInter lpPoint); and the like to get and set the mouse cursor and to simulate double-clicks on certain elements.
For the mouse navigation I already take into consideration
the OS's desktop zoom/scale setting
the IE window Left and Top properties
the location of the IHTMLElement(3).getClientBoundingRect, i.e. the position of the element I wanna trigger
This all works perfectly fine when the IE configuration is the same. My assumptions:
same HTML viewport offset (same toolbars, menus etc)
HTML viewport scaling 100% (no page zooming)
But those two factors are dynamic, so I have to account for them in some way.
So what I need is:
The HTML viewport's vertical offset (in both screenshots it's 106 pixels)
The HTML viewport's horizontal offset (in first its 1, in second it's 291)
The HTML viewport's zoom factor (in both screenshots 100%)
I have tried accessing multiple elements in the ShDocVw.InternetExplorer object, but I either have the wrong interface casts or it does not expose this information willingly, because I could not find it yet.
From a delve into the google world I also came up empty, so no (obvious) answers there either.
So does any one of you know how to deal with this problem? Some obscure COM/OLE incantations and rituals that could guide the mouse cursor on its way?
EDIT:
Dirty solution: I could display some homemade HTML/JS page first, that detects my simulated mouse movement and dump that information into some (invisible) div, then read that data in C#.
Though this is a solution, it's quite ugly and not useful for taking into account layout/display changes that might occur during later runtime, if user changes zooms while the app is working.

Getting the largest image from HTML page source in C#

Basically, what I'm trying to do is get an image to represent a page (for quick browsing in a XAML GridView).
I have the pages URL (and it's HTML content), but now I'm not completely sure how to proceed. I could just use the Favicon, but I don't think that would scale well up to the 200x200 box I'm using to display it. The other option (as far as I can think of) is to look through the HTML source and pick out the largest image.
Is there an easier/simpler way to do that in C# other than just using Regexs to find the height/width of all the image tags and then comparing them?
Thanks!
There is no way to know for sure from the HTML source what size the images are. An img tag doesn't require the height and width parameters. If they're not specified, then the image is displayed in its actual size. If all the img tags on the page have their height and width specified, you could pick the one that has the largest values. But those are the display sizes. The actual sizes might be quite different.
The only way to be 100% sure is to download each image and get its size.
By the way, if you're parsing HTML, you probably shouldn't be doing it with regular expressions. I know it seems simple enough, but you're almost certain to get things wrong and not handle some common cases. You'll save yourself a lot of time and frustration by using something like the Html Agility Pack.
you can try
imageObject.ActualWidth
imageObject.ActualHeight
properties

Remove jquery script from a control

I am coding a galery in jquery.
I have an image zoom tool that is put on a main image on an image_preload event.
I have smaller images that when clicked swaps the main image out with the one that is clicked. The new image is now the main image.
The problem is that the zoom tool is still picking up the old image even though in firebug it says that the new image was loaded into the zoomer.
I want to remove the code that i have on the main image when the switch is made and then put it back on. I'm thinking this will update the zoomer.
i have
$('.MYCLASS').jqzoom();
so can i do something like
$('.MYCLASS').jqzoom().Remove();
Thanks any help is appreciated
You would have to know what the function does in order to reverse its effects. It might be that the plugin provides a remove function, but I doubt that it would work in your instance.
One suggestion might be to simply clone the $('.MYCLASS') element and delete the original which has been bound with the jqzoom() plugin.

Calculate area of HTML element on website?

I'm trying to figure out if it's possible to calculate the area of a HTML element on a website? In pixels, as a percentage or whatever.
My first thoughts have been to make the assumption that the element is 100% in width and height, and then try to retrieve the size through a mapping between the HTML and CSS.
So if there's a width/height attribute in the referenced CSS-file I could possibly say that
the body element is covered by a column that takes 25% of the area (everything is based on your screen resolution of course - and I'm still trying to figure out how I'd be able to do this programmatically).
Or whether I should render the website and do my calculations based on an image with the most common screen resolution at the time).
Are there any more possible solutions?
(Currently I'm trying to solve this in Perl, but I suppose any language that's got a library for this purpose would be appreciated to know about!)
EDIT: I need to retrieve the visual area for every single element on a page.
For example; if there are elements on top of the <body> element, that covers it visually, I want to exclude that area from the <body>'s and so on. A simple raytracing to find the visible area for every element on a page.
EDIT: Let's say we exclude JavaScript - any other approaches possible?
Personally, I would use jQuery - even if you don't use a library, your best bet will be a JavaScript solution.
var $elt = $('#some-element-id'),
height = $elt.height(),
width = $elt.width(),
area = height * width; // contains the area in px^2
http://api.jquery.com/height and http://api.jquery.com/width
This is such a simple problem I don't think JQuery is necessary if you are not already using it.
Try running this:
<div id="myParent">
What's up?
<div id="myDiv">Hello there!</div>
</div>
With
var myDiv = document.getElementById("myDiv");
alert(myDiv.offsetHeight);
alert(myDiv.offsetWidth);
var myParent = myDiv.parentNode;
alert(myParent.offsetHeight);
alert(myParent.offsetWidth);
Divide resulting widths to get % of space the element takes in it's parent, or simply use the absolute pixel values.
I would recommend using jQuery to do it if possible.
alert('Size: ' + $('li').size());
http://api.jquery.com/size/
Would it be feasible to use javascript? If so you can get the width/height with something like this:
document.getElementById(YourElementsId).style.height;
document.getElementById(YourElementsId).style.width;
However this does depening on how the elements are sytled in the first place. Another option would be
document.getElementById(YourElementsId).clientHeight;
document.getElementById(YourElementsId).clientWidth;

Control.PointToScreen gives different results - why?

I have some Label controls sitting on Panel controls on a Form. I want to get the labels' positions relative to the form's origin so that at run time I can hide the panel and the labels and draw some other text in their place directly onto the form.
Basically, I'm doing the following calculation: Get the absolute screen position of a label with Control.PointToScreen() and convert it back to a relative position with Control.PointToClient(), so either:
Dim newloc As Point = Me.PointToClient(ctl.PointToScreen(Point.Empty))
or
Dim newloc As Point = Me.PointToClient(ctl.Parent.PointToScreen(ctl.Location))
I have found that the two methods sometimes give me different results - putting my new point out of the visible area with negative values! - but haven't been able to determine why. I would have thought they should be identical (and they are, most of the time).
Reading the docs didn't help the first time around, but perhaps I skipped over something... Anyway, I'd be thankful for any help before I start tearing my hair out.
Or, on the other hand, is there a better way to do this?
Edit: Sample results
So, here's a real example.
Label1 at {X=4,Y=6} on Panel1; Label2 at {X=163,Y=6} on the same parent, Panel1. Obviously I'm expecting different X-positions, but Y should be identical for both.
When I run the project both ctl.PointToScreen(Point.Empty) and ctl.Parent.PointToScreen(ctl.Location) give me the same screen location for Label1 at {X=959,Y=119} (the absolute values here can vary, of course, depending on the position of the form itself) and therefore the correct location relative to the form when Me.PointToClient is applied (at {X=5,Y=32}).
The very next lines do the same calculations for Label2 (remember, same Parent, same Y-value within the parent (6)), but the results are totally off: ctl.Parent.PointToScreen() gives me {X=1114,Y=63}. X is almost correct (959-4+163=1118), but Y is nowhere near the 119 I got for Label1. And then ctl.PointToScreen() gives me {X=166,Y=29} - translated back to Form-Coordinates (Me.PointToClient) {X=-784,Y=-2}.
These numbers are calculated and printed to the debug window directly after each other, without moving anything around... Madness.
OK, this is getting rather messy, but I still hope someone has a simple explanation. Thanks!
OK, I found the solution.
I happened to be calling Control.PointToScreen before the control was created: Control.IsHandleCreated = False.
If I ensure that the control is created first (Control.CreateControl) both methods work equally well.
The reason I had differing results on subsequent calls is that the first call to Control.PointToScreen also causes the control to be created (and therefore its parent and any other controls sited on the parent), meaning the second succeeds.
Well, I'm sure glad to be done with this :-)
I think it's the sleep. :) Instead of:
ctl.PointToScreen(Point.Empty)
ctl.Parent.PointToScreen(ctl.Location)
try:
ctl.PointToScreen(Point.Empty)
ctl.PointToScreen(ctl.Location) // Note no .Parent!
instead and you'll see the difference in the x/y coordinates.
Also, try using Control.TopLevelControl or Control.FindForm() to get the outermost Form when doing your PointToScreen math.

Categories