可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I was wondering if its possible to get the absolute position of specific HTML element I have loaded in webbrowser control with C#.
I tried almost all of the options that .Net provides.. none of them give me the correct position. all of them give me 0 for Y coordinate.. the element is definitely is not in 0..
does anybody have any solution or idea to solve this?
回答1:
here is the solution I got so far:
// set the size of our web browser to be the same size as the image int width, height; width = webBrowser1.Document.Images[0].ClientRectangle.Width; height = webBrowser1.Document.Images[0].ClientRectangle.Height;
webBrowser1.Width = width; webBrowser1.Height = height; //scroll vertically to that element webBrowser1.Document.Images[0].OffsetParent.ScrollIntoView(true); //calculate x, y offset of the element int x = webBrowser1.Document.Images[s].OffsetRectangle.Left + webBrowser1.Document.Images[s].OffsetParent.OffsetRectangle.Left + webBrowser1.Document.Images[s].OffsetParent.OffsetParent.OffsetRectangle.Left+ webBrowser1.Document.Images[s].OffsetParent.OffsetParent.OffsetParent.OffsetRectangle.Left+ webBrowser1.Document.Images[s].OffsetParent.OffsetParent.OffsetParent.OffsetParent.OffsetRectangle.Left; int y = webBrowser1.Document.GetElementsByTagName("HTML")[0].ScrollTop; //now scroll to that element webBrowser1.Document.Window.ScrollTo(x, y);
now this code works perfectly.. but there is an issue with calculating the offsets. I need to calculate the offsetparent of the element then calculate the offsetparent of the offsetparent etc.. I need to do that dynamically not adding it one by one.. I don't know how to do that. any ideas?
EDIT: here is my last and final version and it works with any html element it will find the absolute position of any element I want..
public int getXoffset(HtmlElement el) { //get element pos int xPos = el.OffsetRectangle.Left; //get the parents pos HtmlElement tempEl = el.OffsetParent; while (tempEl != null) { xPos += tempEl.OffsetRectangle.Left; tempEl = tempEl.OffsetParent; } return xPos; } public int getYoffset(HtmlElement el) { //get element pos int yPos = el.OffsetRectangle.Top; //get the parents pos HtmlElement tempEl = el.OffsetParent; while (tempEl != null) { yPos += tempEl.OffsetRectangle.Top; tempEl = tempEl.OffsetParent; } return yPos; }
then use the position with:
//now scroll to that element webBrowser1.Document.Window.ScrollTo(x, y);
done!
回答2:
I like previous answers but iterating through parent objects twice is not very effective. Remember - you're working with COM/ActiveX here. This works much faster:
public Point GetOffset(HtmlElement el) { //get element pos Point pos = new Point(el.OffsetRectangle.Left, el.OffsetRectangle.Top); //get the parents pos HtmlElement tempEl = el.OffsetParent; while (tempEl != null) { pos.X += tempEl.OffsetRectangle.Left; pos.Y += tempEl.OffsetRectangle.Top; tempEl = tempEl.OffsetParent; } return pos; }
and then
var point = GetOffset(element); var x = point.X; var y = point.Y;
回答3:
Thank you, it works like a charm. I had to rewrite it as VB, and just want to share the solution:
Function GetXOffSet(ByVal elem As HtmlElement) As Integer Dim xPos As Integer = elem.OffsetRectangle.Left Dim tElm As HtmlElement = elem.OffsetParent Dim trig As Boolean = False While Not trig Try xPos += tElm.OffsetRectangle.Left tElm = tElm.OffsetParent Catch ex As Exception trig = True End Try End While Return xPos End Function Function GetYOffSet(ByVal elem As HtmlElement) As Integer Dim yPos As Integer = elem.OffsetRectangle.Top Dim tElm As HtmlElement = elem.OffsetParent Dim trig As Boolean = False While Not trig Try yPos += tElm.OffsetRectangle.Top tElm = tElm.OffsetParent Catch ex As Exception trig = True End Try End While Return yPos End Function
回答4:
There is a direct way to get the coordinates. IHTMLElement2 has the method getBoundingClientRect that gives you the coordinates of the element.
IHTMLDocument3 doc = (IHTMLDocument3)this.webbrowser.Document; IHTMLElement2 element = (IHTMLElement2)doc.getElementById(idElement); IHTMLRect rect = element.getBoundingClientRect(); int x = rect.left; int y= rect.top;
回答5:
Just sharing a slightly different implementation based on my needs to get the absolute positioning retangle:
public Rectangle GetAbsoluteRectangle(HtmlElement element) { //get initial rectangle Rectangle rect = element.OffsetRectangle; //update with all parents' positions HtmlElement currParent = element.OffsetParent; while (currParent != null) { rect.Offset(currParent.OffsetRectangle.Left, currParent.OffsetRectangle.Top); currParent = currParent.OffsetParent; } return rect; }
回答6:
Not sure why but offsetparent is not allways returned (case of IE11, map object) I had to add parentElement in the loop when parentOffset is not provided
While parent IsNot Nothing y += parent.offsetTop x += parent.offsetLeft If parent.offsetParent IsNot Nothing Then parent = parent.offsetParent Else parent = parent.parentElement End If End While
And you need to add IE browser position, the menu space and borders ...
回答7:
The cleanest way that works for me is the following:
HtmlElement elem = webBrowser.Document.GetElementById(idElement); IHTMLRect rect = ((IHTMLElement2) elem.DomElement).getBoundingClientRect(); // rect.top and rect.left represent absolute coordinates.