You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm WebBrowser控件:如何获取选中区域的HTML内容

WinForm WebBrowser控件获取选中区域HTML内容解决方案

我有一个WinForm项目,使用WebBrowser控件加载包含大量HTML表格的网站。用户会通过鼠标在WebBrowser中选中包含多个HTML表格的大段内容。目前已实现获取选中文本的功能,但需要编程获取选中区域的HTML内容,现有代码无法满足需求,请求正确实现方案。

已实现的选中文本获取代码

private string GetSelectedText()
{
    dynamic document = webBrowser1.Document.DomDocument;
    dynamic selection = document.selection;
    dynamic text = selection.createRange().text;
    return (string)text;
}

现有无效代码(仅能处理单个表格,无法获取多表格选中区域的HTML)

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HtmlTableParser
{
    public partial class Form2 : Form
    {
        private WebBrowser webBrowser1;
        public Form2()
        {
            InitializeComponent();

            Button btn = new Button();
            btn.Text = "Test";
            btn.Click += button1_Click;
            this.Controls.Add(btn);

            var panel = new Panel();
            panel.Top = btn.Height + 2;
            panel.Height = this.ClientSize.Height - btn.Height + 2;
            panel.Width = this.ClientSize.Width;
            panel.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;

            webBrowser1 = new WebBrowser();
            webBrowser1.Dock = DockStyle.Fill;
            webBrowser1.Url = new Uri("https://www.sec.gov/Archives/edgar/data/1108134/000110813423000018/bhlb-20230630.htm");

            panel.Controls.Add(webBrowser1);
            this.Controls.Add(panel);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            TestSelection();
            TestAllTable();
        }

        private void TestSelection()
        {
            var domdoc = this.webBrowser1.Document.DomDocument as mshtml.IHTMLDocument2;
            var sel = domdoc.selection;
            var range = sel.createRange();
            var trange = range as mshtml.IHTMLTxtRange;

            var table = GetParentTable(trange.parentElement());
            if (table == null)
            {
                var startPointRange = trange.duplicate();
                startPointRange.setEndPoint("EndToStart", trange);
                var startPointTable = GetParentTable(startPointRange.parentElement());

                var endPointRange = trange.duplicate();
                startPointRange.setEndPoint("StartToEnd", trange);
                var endPointTable = GetParentTable(endPointRange.parentElement());

                if (startPointTable != null)
                {
                    table = startPointTable;
                }
                else if (endPointTable != null)
                {
                    table = endPointTable;
                }
                else
                {
                    MessageBox.Show("Selection is not in Table");
                    return;
                }
            }

            var tableData = TableData.GetTableData(table);

            System.Diagnostics.Debug.WriteLine(tableData.ToString());
        }

        private mshtml.IHTMLTable GetParentTable(mshtml.IHTMLElement element)
        {
            var parent = element;
            while (parent != null)
            {
                if (parent is mshtml.IHTMLTable table)
                {
                    return table;
                }
                parent = parent.parentElement;
            }
            return null;
        }

        private void TestAllTable()
        {
            var domdoc = this.webBrowser1.Document.DomDocument as mshtml.HTMLDocument;
            foreach (var table in domdoc.getElementsByTagName("table").OfType<mshtml.IHTMLTable>())
            {

                var tableData = TableData.GetTableData(table);

                System.Diagnostics.Debug.WriteLine(tableData.ToString());
                System.Diagnostics.Debug.WriteLine(new string('=', 20));
            }
        }

    }

    class TableData
    {
        public static TableData GetTableData(mshtml.IHTMLTable table)
        {
            TableData tableData = new TableData();

            foreach (var tableRow in table.rows.OfType<mshtml.IHTMLTableRow>())
            {
                RowData rowdata = new RowData();
                foreach (var tablecell in tableRow.cells.OfType<mshtml.HTMLTableCell>())
                {
                    CellData cell = new CellData();
                    cell.Text = tablecell.innerText;
                    cell.RowSpan = tablecell.rowSpan;
                    cell.ColSpan = tablecell.colSpan;
                    rowdata.Add(cell);
                }

                tableData.Rows.Add(rowdata);
            }

            return tableData;
        }

        public List<RowData> Rows { get; } = new List<RowData>();

        public override string ToString()
        {
            System.Text.StringBuilder sb = new StringBuilder();
            foreach (var row in this.Rows)
            {
                sb.AppendLine(row.ToString());
            }
            return sb.ToString();
        }
    }

    class RowData : List<CellData>
    {
        public override string ToString()
        {
            return string.Join("\t", this.Select(cell => cell.Text + new string('\t', cell.ColSpan)));
        }
    }

    class CellData
    {
        public string Text { get; set; }
        public int ColSpan { get; set; }
        public int RowSpan { get; set; }

        public override string ToString() => Text;
    }
}

选中内容示例

选中区域示例


正确实现方案

前置准备

确保项目已添加Microsoft HTML Object Library COM引用(右键项目→添加→引用→COM→找到并勾选)。

核心代码

private string GetSelectedHtml()
{
    // 获取DOM文档对象
    var domDoc = webBrowser1.Document.DomDocument as mshtml.IHTMLDocument2;
    if (domDoc == null || domDoc.selection == null)
        return string.Empty;

    var selection = domDoc.selection;
    var range = selection.createRange();

    // 处理文本范围选中(用户拖动鼠标选中的多表格大段内容)
    var txtRange = range as mshtml.IHTMLTxtRange;
    if (txtRange != null)
    {
        // 返回选中范围的完整HTML内容
        return txtRange.htmlText;
    }

    // 处理元素范围选中(比如右键选中的单个/多个元素)
    var ctrlRange = range as mshtml.IHTMLControlRange;
    if (ctrlRange != null && ctrlRange.length > 0)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < ctrlRange.length; i++)
        {
            var elem = ctrlRange.item(i) as mshtml.IHTMLElement;
            if (elem != null)
                sb.Append(elem.outerHTML);
        }
        return sb.ToString();
    }

    return string.Empty;
}

使用示例

在按钮点击事件中调用该方法,即可获取选中区域的HTML:

private void button1_Click(object sender, EventArgs e)
{
    string selectedHtml = GetSelectedHtml();
    // 输出或进一步解析HTML内容
    System.Diagnostics.Debug.WriteLine(selectedHtml);
}

关键说明

  • txtRange.htmlText会返回选中范围内的完整HTML,包括所有嵌套表格和元素,完美支持多表格选中场景。
  • 兼容两种选中模式:文本范围选中(用户拖动鼠标的任意选择)和元素范围选中(右键选择的元素)。

内容的提问来源于stack exchange,提问作者Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:44:52