1

Internet Explorer を使用して、人がテキストをクリックした位置を取得したいと思います。3~4文字の誤差は問題ありません。テキストは編集できず、通常はスパン要素にあります。

HTMLDocument のクリック イベント リスナーを設定できることは承知していますが、常に HTMLDocument オブジェクトを持っているとは限らないため、イベントを見逃す可能性があります。

IHTMLSelectionObject を取得してから、IHTMLTxtRange でテキスト範囲を作成しようとしましたが、少なくとも 1 文字が選択されているのではなく Web ページが単にクリックされた場合、IHTMLTxtRange にはクリックされた要素ではなく、HTMLBody の親があります。 .

HTMLDocument.activeElement も信頼できません。私のテストでは、クリックされた要素を実際に返すことはありません。通常、ツリーのどこかにある要素の主要な親を返します。

MSHTML を使用してこれを達成する別の方法はありますか?

WIN API GetCursorPos も使用してみましたが、この位置をどうするかわかりません。これを実際の要素に変換する方法がわかりません。

編集: 私も面白いアイデアを考えました。カーソルのある要素を知る必要がある場合は、ドキュメント全体に mouseDown またはクリック イベントを設定します。次に、自分のクリックを発生させ、イベントをキャッチします。イベントの 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 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
4

1 に答える 1

0

これを行う方法を示す素晴らしい機能で回答を投稿することはできませんが、重要な部分について説明します。

  1. Win32 API GetCursorPos を使用して、ユーザーが最後にクリックした画面上のポイントを取得します。
  2. 複数の HTMLDocument を意味する iFrame がある場合は、iFrame をループ処理し、HTMLFrameElement の clientWidth と clientHeight を IHTMLWindow3 screenTop と screenLeft と共に使用して、ポイントがどの HTMLDocument にあるかを調べる必要があります。
  3. 2 番で見つけた IHTMLWindow を使用して、この点を相対点に変換します。
  4. 適切な HTMLDocument と、このドキュメントに関連するポイントを取得したら、IHTMLDocument2 オブジェクトで elementFromPoint メソッドを使用できます。
  5. これを取得すると、クリックされたポイントと要素がわかります。

    ブール値としてのプライベート関数 getElementTextPosition()

        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
    
于 2016-01-25T06:50:21.827 に答える