如何获取HTML元素以及人物点击的元素文本中的位置

时间:2016-01-20 16:06:36

标签: vb.net mshtml shdocvw

使用Internet Explorer我想获得一个人点击文本的位置。 3到4个字符的错误很好。该文本不可编辑,通常位于span元素中。

我知道我可以为HTMLDocument设置一个click事件监听器,但是我并不总是有HTMLDocument对象,因此可能会错过该事件。

我尝试获取IHTMLSelectionObject,然后使用IHTMLTxtRange创建文本范围,但是当简单地单击网页而不是选择至少1个字符时,IHTMLTxtRange具有HTMLBody的父级而不是元素的父级点击了。

HTMLDocument.activeElement也不可靠。在我的测试中,它实际上永远不会返回单击的元素,它通常会在树的某个位置返回元素的主要父元素。

使用MSHTML还有另一种方法可以实现吗?

我也尝试过使用WIN API GetCursorPos但是我不知道如何处理这个位置,我不知道如何将它转换为实际的元素。

修改 我还想到了一个有趣的想法。当我需要知道带有光标的元素时,我在整个文档上设置了mouseDown或click事件。然后开火我自己的点击并抓住事件。在事件的IHTMLEventObj中是一个FromElement,我希望它能告诉我光标在哪里。对于mouseDown和click事件似乎总是没有任何意义。对我来说,至少这个对象仅用于鼠标悬停事件。

以下是我选择至少一个角色时的情况。

 Private Function GetHTMLSelection(ByVal aDoc As IHTMLDocument2, ByRef htmlText As String) As Integer

    Dim sel As IHTMLSelectionObject = Nothing
    Dim selectionRange As IHTMLTxtRange = Nothing
    Dim rangeParent As IHTMLElement4 = Nothing
    Dim duplicateRange As IHTMLTxtRange = Nothing
    Dim i As Integer
    Dim x As Integer
    Dim found As Boolean

    Try
        'get a selection
        sel = TryCast(aDoc.selection, IHTMLSelectionObject)

        If sel Is Nothing Then
            Return -1
        End If
        'the the range of the selection.
        selectionRange = TryCast(sel.createRange, IHTMLTxtRange)

        If selectionRange Is Nothing Then
            Return -1
        End If
        'the the parent element of the range.
        rangeParent = TryCast(selectionRange.parentElement, IHTMLElement4)

        'duplicate our range so we can manipulate it.
        duplicateRange = TryCast(selectionRange.duplicate, IHTMLTxtRange)

        'make the dulicate range the whole element text.
        duplicateRange.moveToElementText(rangeParent)

        'get the length of the whole text
        i = duplicateRange.text.Length

        For x = 1 To i
            duplicateRange.moveStart("character", 1)

            If duplicateRange.compareEndPoints("StartToStart", selectionRange) = 0 Then
                found = True
                Exit For
            End If

        Next

        If found Then
            Debug.Print("Position is: " + x.ToString)
            htmlText = duplicateRange.text
            Return x
        Else
            Return -1
        End If


    Catch ex As Exception
        Return -1
    Finally

    End Try


End Function

1 个答案:

答案 0 :(得分:0)

我不能用一个很好的函数发布答案,说明如何做到这一点,但我将解释重要的部分。

  1. 使用Win32 API GetCursorPos获取用户上次点击的屏幕上的点。
  2. 如果你有iFrames意味着多个HTMLDocument,那么你需要遍历你的iFrames并使用HTMLFrameElement clientWidth和clientHeight以及IHTMLWindow3 screenTop和screenLeft来找出你的观点所在的HTMLDocument。
  3. 使用您在数字2中找到的IHTMLWindow将此点转换为相对点。
  4. 一旦有了正确的HTMLDocument和相对于该文档的点,就可以在IHTMLDocument2对象上使用elementFromPoint方法。
  5. 一旦你有了这个,你现在知道点击的点和元素。

    私有函数getElementTextPosition()As Boolean

        Dim sel As IHTMLSelectionObject = Nothing
        Dim selectionRange As IHTMLTxtRange = Nothing
        Dim duplicateRange As IHTMLTxtRange = Nothing
        Dim i As Integer = 0
        Dim found As Boolean
        Dim x As Integer
    
        Try
            'elementWithCursor is a IHTMLElement class variable
            If elementWithCursor IsNot Nothing Then
                ReleaseComObject(elementWithCursor)
                elementWithCursor = Nothing
            End If
            'docWithCursor is also a IHTMLDocument2 class variable
            'cursorPointInDoc is the point relative to the actual document 
            elementWithCursor = TryCast(docWithCursor.elementFromPoint(cursorPointInDoc.X, cursorPointInDoc.Y), IHTMLElement)
    
            If elementWithCursor Is Nothing Then
                Return False
            End If
    
            'get a selection
            sel = TryCast(docWithCursor.selection, IHTMLSelectionObject)
    
            If sel Is Nothing Then
                Return False
            End If
    
            selectionRange = TryCast(sel.createRange, IHTMLTxtRange)
    
            If selectionRange Is Nothing Then
                Return False
            End If
    
            'First check if We have selection text so we will use that as the selected text
            '_SelectedText relates to a class property
            If selectionRange.text IsNot Nothing Then
                _SelectedText = selectionRange.text
                selectionRange.collapse(True)
            Else
                'the the parent element of the range.
                selectionRange.moveToPoint(cursorPointInDoc.X, cursorPointInDoc.Y)
            End If
    
            'duplicate our range so we can manipulate it.
            duplicateRange = TryCast(selectionRange.duplicate, IHTMLTxtRange)
    
            'make the dulicate range the whole element text.
            duplicateRange.moveToElementText(elementWithCursor)
    
            'get the length of the whole text
            i = duplicateRange.text.Length
    
            For x = 0 To i
    
                If duplicateRange.compareEndPoints("StartToStart", selectionRange) = 0 Then
                    found = True
                    Exit For
                End If
    
                duplicateRange.moveStart("character", 1)
    
            Next
    
            If found Then
                '_CursorPositionInText is a class property and relates to the position where the person clicked in the html text.
                _CursorPositionInText = x
                _HTMLElementText = elementWithCursor.innerText
    
                Return True
            Else
                Return False
            End If
    
        Catch ex As Exception
            Return False
        End Try
    
    End Function