在WebBrowser中标识游标下的HtmlElement

时间:2017-02-28 19:52:42

标签: html vb.net winforms dom

我正在尝试将WebBrowser控件的小扩展设置为HtmlTextBox,格式化的可能性有限。它适用于基本格式(粗体,斜体,下划线)。但我也想在一个单一级别允许缩进,理想情况下以“切换”方式调用它。

我注意到,当我运行Document.ExecCommand("Indent", False, Nothing)时,它会将<p>元素转换为<blockquote>元素,这正是我需要的。但是对同一命令的第二次调用只会增加缩进余量,但是我想这样做,如果游标已经在<blockquote>元素内,它将执行“outdent”。

为此,我尝试在执行操作之前查询Document.ActiveElement,但这会返回整个<body>元素,而不是当时光标所在的特定块元素。

我怎么能做到这一点?

这是我的代码:

Public Class HtmlTextBox
    Inherits WebBrowser

    Public Sub New()
        WebBrowserShortcutsEnabled = False
        IsWebBrowserContextMenuEnabled = False
        DocumentText = "<html><body></body></html>"
        If Document IsNot Nothing Then
            Dim doc = Document.DomDocument
            If doc IsNot Nothing Then
                doc.designMode = "On"
                If Me.ContextMenuStrip Is Nothing Then
                    AddHandler Document.ContextMenuShowing, Sub(sender As Object, e As HtmlElementEventArgs) Application.DoEvents()
                End If
            End If
        End If
    End Sub
    Private Sub HtmlTextBox_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles Me.PreviewKeyDown
        If e.Control Then
            If e.KeyData.HasFlag(Keys.B) OrElse e.KeyData.HasFlag(Keys.N) Then BoldToggle()
            If e.KeyData.HasFlag(Keys.I) Then ItalicToggle()
            If e.KeyData.HasFlag(Keys.S) OrElse e.KeyData.HasFlag(Keys.U) Then UnderlineToggle()
            If e.KeyData.HasFlag(Keys.M) Then BlockQuoteToggle()
        End If
    End Sub

    Public Sub BoldToggle()
        Document.ExecCommand("Bold", False, Nothing)
    End Sub

    Public Sub ItalicToggle()
        Document.ExecCommand("Italic", False, Nothing)
    End Sub
    Public Sub UnderlineToggle()
        Document.ExecCommand("Underline", False, Nothing)
    End Sub
    Public Sub BlockQuoteToggle()
        If Document.ActiveElement.TagName.ToLower = "blockquote" Then
            Document.ExecCommand("Outdent", False, Nothing)
        Else
            Document.ExecCommand("Indent", False, Nothing)
        End If
    End Sub
End Class

1 个答案:

答案 0 :(得分:1)

方法ElementAtSelectionStart旨在返回包含当前选择开头的元素。此代码用于编辑模式下的WebBrowser控件。希望它能满足您的需求。

Public Class mshtmlUtilities
   Public Enum C_Bool
      [False] = 0
      [True] = 1
   End Enum

   Public Shared Function ElementAtSelectionStart(ByVal wb As System.Windows.Forms.WebBrowser) As System.Windows.Forms.HtmlElement
      Dim el As System.Windows.Forms.HtmlElement = Nothing

      If wb IsNot Nothing AndAlso _
         wb.Document IsNot Nothing AndAlso _
         DirectCast(wb.Document.DomDocument, mshtml.IHTMLDocument2).designMode.Equals("on", StringComparison.InvariantCultureIgnoreCase) Then

         Dim doc As mshtml.IHTMLDocument2 = DirectCast(wb.Document.DomDocument, mshtml.IHTMLDocument2)
         Dim sel As mshtml.IHTMLSelectionObject = DirectCast(doc.selection, mshtml.IHTMLSelectionObject)
         Select Case sel.type.ToLowerInvariant
            Case "text"
               Dim rng As mshtml.IHTMLTxtRange = DirectCast(sel.createRange(), mshtml.IHTMLTxtRange)
               rng.collapse(True)
               el = MakeWinFormHTMLElement(rng.parentElement, wb)
            Case "control"
               Dim rng As mshtml.IHTMLControlRange = DirectCast(sel.createRange(), mshtml.IHTMLControlRange)
               el = MakeWinFormHTMLElement(rng.item(0).parentElement, wb)
            Case "none"
               Dim ds As mshtml.IDisplayServices = DirectCast(doc, mshtml.IDisplayServices)
               Dim caret As mshtml.IHTMLCaret = Nothing
               ds.GetCaret(caret)
               Dim pt As mshtml.tagPOINT
               caret.GetLocation(pt, C_Bool.False)
               el = wb.Document.GetElementFromPoint(New Point(pt.x, pt.y))
         End Select
      End If

      Return el
   End Function

   Private Shared Function MakeWinFormHTMLElement(ByVal el As mshtml.IHTMLElement, ByVal wb As System.Windows.Forms.WebBrowser) As System.Windows.Forms.HtmlElement
      Dim shimInfo As Reflection.PropertyInfo = wb.GetType.GetProperty("ShimManager", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
      Dim shimManager As Object = shimInfo.GetValue(wb, Nothing)
      Dim ciElement As Reflection.ConstructorInfo() _
         = wb.Document.Body.GetType().GetConstructors(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
      Return CType(ciElement(0).Invoke(New Object() {shimManager, el}), HtmlElement)
   End Function
End Class
相关问题