32、探索浏览器扩展:BHO与Band对象的实现与应用

探索浏览器扩展:BHO与Band对象的实现与应用

1. 浏览器辅助对象(BHO)的实现与应用

BHO 是一种在浏览器进程内运行的扩展,能让开发者在不依赖 UI 的情况下访问 IE 的事件和功能。下面将详细介绍其实现与应用。

1.1 BHO 的注销功能

要移除 BHO,可使用以下代码注销关联的注册表项:

[ComUnregisterFunction]
public static void Unregister(Type type)
{
    // Open up the main BHO key
    RegistryKey bhoKey =
        Registry.LocalMachine.OpenSubKey(
            @"Software\Microsoft\Windows\CurrentVersion\" +
            @"Explorer\Browser Helper Objects",
            true);

    // Delete the GUID key if it exists
    if (bhoKey != null) bhoKey.DeleteSubKey(
        type.GUID.ToString("B"), false);
}

移除注册表项后,IE 不再加载该 BHO,也不会在“管理加载项”对话框中显示。

1.2 捕获浏览器事件

BHO 不仅能加载到浏览器进程,还可通过 SetSite 方法获取 WebBrowser 实例,进而利用其丰富的功能。其中,捕获浏览器事件是重要应用之一。常见且实用的事件由 DWebBrowserEvents2 接口暴露,如 BeforeNavigate2 (导航前触发)、 NavigationComplete2 (导航完成时触发)和 DocumentComplete (文档完全加载时触发)。

以下是在 SetSite 调用中捕获事件的示例:

[SecurityPermission(SecurityAction.LinkDemand,
    Flags = SecurityPermissionFlag.UnmanagedCode),
ComVisible(true),
Guid("FE19878E-55B9-48AA-B293-2BDEEB2232DB"),
ClassInterface(ClassInterfaceType.None)]
public class BhoSampleEvents : NativeMethods.IObjectWithSite
{
    ...
    public int SetSite(object site)
    {
        // If the site is valid, cast as a WebBrowser object and
        // store it in the Browser variable
        if (site != null)
        {
            // Set the site object, cast as a WebBrowser object,
            // to the Browser variable  
            Browser = (SHDocVw.WebBrowser)site;

            // Add a handler for when navigation starts
            Browser.BeforeNavigate2 += Browser_BeforeNavigate2;

            // Add a handler for when the document has completely loaded
            Browser.DocumentComplete += Browser_DocumentComplete;
        }
        else
        {
            // Detatch the event handlers if they were attached
            Browser.BeforeNavigate2 -= Browser_BeforeNavigate2;
            Browser.DocumentComplete -= Browser_DocumentComplete;

            // Set the browser object to null
            Browser = null;
        }

        return S_OK;
    }
}
1.3 事件回调函数
  • BeforeNavigate2 事件回调
void Browser_BeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object  
    TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
{
    // If the site or url is null, do not continue
    if (pDisp == null || URL == null) return;

    // Convert the url object reference to a string
    string url = URL.ToString();

    // Show the url in a message box
    MessageBox.Show("Begin navigation to: " + url);
}

该函数在特定标签页导航前显示包含目标 URL 的消息框。

  • DocumentComplete 事件回调
void Browser_DocumentComplete(object pDisp, ref object URL)
{
    // If the site or url is null, do not continue
    if (pDisp == null || URL == null) return;

    // Grab the document object off of the WebBrowser control
    IHTMLDocument2 document = (IHTMLDocument2)Browser.Document;
    if (document == null) return;

    // Report the total number of links on the current page
    MessageBox.Show("Total links on this page: " +
        document.links.length.ToString());
}

此函数在文档加载完成后,显示当前页面的链接总数。

需要注意的是, DocumentComplete 事件在页面加载时可能会多次触发,每次加载一个框架都会触发一次,最后顶级窗口加载完成时也会触发。开发者可通过比较传递给事件处理程序的 pDisp 指针与顶级窗口的 pDisp 指针来区分。

同时,由于回调函数在 IE UI 线程中运行,运行时会占用用户控制权,因此应尽量减少在这些函数中的处理时间,或另起线程处理事件。

2. 使用 Band 对象扩展浏览器框架

Band 对象为开发者提供了扩展 Windows 外壳和 IE 浏览器框架的途径,能在浏览器界面的显著位置展示内容。下面将介绍三种常见的 Band 对象:工具栏、垂直资源管理器栏和水平资源管理器栏。

2.1 Band 对象概述

IE 提供了三个主要区域用于显示 Band 对象:工具栏区域、窗口左侧(垂直资源管理器栏区域)和窗口底部(水平资源管理器栏区域)。这些对象可在 IE 的“工具”菜单中管理,也能通过“管理加载项”窗口进行管理。关闭 Band 对象时,它们仍会保留在内存中,直到浏览器重启。

2.2 构建通用 Band 对象

所有类型的 Band 对象都基于相同的构建块,包括用户界面和用于连接浏览器、Windows 外壳和 COM 的接口。在 .NET 代码中,主要由通用的 UserControl 和一系列非托管接口组成。

以下是 BandObject 类的基本架构:

public class BandObject : UserControl,  
                          IObjectWithSite,   
                          IDeskBand, IDockingWindow,  
                          IOleWindow
{
    #region Static Members ...
    #region Instance Members ...
    #region Virtual Methods ...
    #region IObjectWithSite Interface Implementation ...
    #region IOleWindow Interface Implementation ...
    #region IDockingWindow Interface Implementation ...
    #region IOLECommandTarget Interface Implementation ...
    #region COM Registration Methods ...
}

该类可进一步划分为以下几个部分:
- 静态成员 :定义元数据,如大小、标题等,供派生类使用。

#region Static Members
public static string ClassId;
public static string ProgId;
public static string ObjectTitle;
public static string ObjectName;
public static string HelpText;

public static new Size InitialSize;
public static Size MinSize;
public static Size MaxSize;
public static Size IntegralSize;

public static BandObjectTypes Style = BandObjectTypes.HorizontalExplorerBar;
#endregion Static Members

其中, Style 变量用于定义 Band 对象的类型,通过 BandObjectTypes 枚举指定:

public enum BandObjectTypes
{
    VerticalExplorerBar = 1,
    Toolbar = 2,
    HorizontalExplorerBar = 4     
}
  • 实例成员 :存储与 IWebBrowser 和 IE 应用程序站点的引用。
#region Instance Members
public SHDocVw.WebBrowserClass WebBrowser;
public SHDocVw.InternetExplorer BandObjectSite;
#endregion Instance Members
  • 虚拟方法 DefineMetadata 方法用于设置静态元数据。
#region Virtual Methods
public void DefineMetadata() { }
#endregion Virtual Methods
  • 接口实现
    • IObjectWithSite 接口 :用于获取和设置对象加载的“站点”(COM 对象),即 IE 浏览器对象。
#region IObjectWithSite Interface Implementation
public void SetSite(object pUnkSite)
{
    if (!(pUnkSite is SHDocVw.InternetExplorer))
    {
        if (BandObjectSite != null)
        {
            Marshal.ReleaseComObject(BandObjectSite);
            BandObjectSite = null;
        }
        return;
    }
    try
    {
        BandObjectSite = (SHDocVw.InternetExplorer)pUnkSite;
        ProIeDev.BandObjectDemo.Interop.Interfaces.IServiceProvider serviceProvider =
            (ProIeDev.BandObjectDemo.Interop.Interfaces.IServiceProvider)
                BandObjectSite;
        object pUnknown = null;
        Guid guid = new Guid(IID.IID_IWebBrowserApp);
        Guid riid = new Guid(IID.IID_IUnknown);
        serviceProvider.QueryService(ref guid, ref riid, out pUnknown);
        WebBrowser = (SHDocVw.WebBrowserClass)Marshal.CreateWrapperOfType(
            pUnknown as IWebBrowser, typeof(SHDocVw.WebBrowserClass));
        object pvaClsid = (object)ClassId;
        object pvarSize = null;
        object pvarShowTrue = (object)true;
        WebBrowser.ShowBrowserBar(ref pvaClsid, ref pvarShowTrue, ref pvarSize);
    }
    catch (Exception) { }
}
public void GetSite(ref Guid riid, out object ppvSite)
{
    ppvSite = BandObjectSite;
}
#endregion IObjectWithSite Interface Implementation
- **IDeskBand 接口**:用于获取即将加载到 Windows 外壳或 IE 中的 Band 对象的信息。
#region IDeskBand Interface Implementation
public void GetBandInfo(uint dwBandID, uint dwViewMode, ref DESKBANDINFO pdbi)
{
    try
    {
        if ((pdbi.dwMask & DBIM.TITLE) == DBIM.TITLE)
            pdbi.wszTitle = ObjectTitle;
        if ((pdbi.dwMask & DBIM.ACTUAL) == DBIM.ACTUAL)
        {
            pdbi.ptActual.X = InitialSize.Width;
            pdbi.ptActual.Y = InitialSize.Height;
        }
        if ((pdbi.dwMask & DBIM.MAXSIZE) == DBIM.MAXSIZE)
        {
            pdbi.ptMaxSize.X = MaxSize.Width;
            pdbi.ptMaxSize.Y = MaxSize.Height;
        }
        if ((pdbi.dwMask & DBIM.MINSIZE) == DBIM.MINSIZE)
        {
            pdbi.ptMinSize.X = MinSize.Width;
            pdbi.ptMinSize.Y = MinSize.Height;
        }
        if ((pdbi.dwMask & DBIM.INTEGRAL) == DBIM.INTEGRAL)
        {
            pdbi.ptIntegral.X = IntegralSize.Width;
            pdbi.ptIntegral.Y = IntegralSize.Height;
        }
        if ((pdbi.dwMask & DBIM.BKCOLOR) == DBIM.BKCOLOR)
            pdbi.dwMask &= ~DBIM.BKCOLOR;
        if ((pdbi.dwMask & DBIM.MODEFLAGS) == DBIM.MODEFLAGS)
        {
            pdbi.dwModeFlags = DBIMF.VARIABLEHEIGHT | DBIMF.NORMAL;
            if (Style == BandObjectTypes.Toolbar)
                pdbi.dwModeFlags |= DBIMF.BREAK | DBIMF.ALWAYSGRIPPER;
        }
    }
    catch (Exception) { }
}
#endregion IDeskBand Interface Implementation
- **IOleWindow 接口**:允许处理 OLE 窗口调用,主要使用 `GetWindow` 方法返回 `UserControl` 实例的窗口句柄。
#region IOleWindow Interface Implementation
public void GetWindow(out IntPtr phwnd)
{
    phwnd = Handle;
}

public void ContextSensitiveHelp(bool fEnterMode)
{
    return;
}
#endregion IOleWindow Interface Implementation

总结

BHO 和 Band 对象为开发者提供了扩展 IE 功能的有效途径。BHO 能在浏览器进程内运行,捕获浏览器事件,增强页面功能;Band 对象则可扩展浏览器框架,在显著位置展示内容。通过合理运用这些技术,开发者能为用户带来更丰富的浏览器体验。

以下是 BHO 和 Band 对象的特点对比表格:
| 类型 | 运行方式 | 功能特点 | 应用场景 |
| ---- | ---- | ---- | ---- |
| BHO | 进程内运行 | 捕获浏览器事件,无需 UI | 监控页面加载、导航等事件 |
| Band 对象 | 扩展浏览器框架 | 提供 UI 展示,可在工具栏、侧边栏等位置显示 | 增强浏览器界面功能 |

mermaid 流程图展示 BHO 事件处理流程:

graph LR
    A[浏览器事件触发] --> B{事件类型}
    B -->|BeforeNavigate2| C[调用 BeforeNavigate2 回调]
    B -->|DocumentComplete| D[调用 DocumentComplete 回调]
    C --> E[显示导航信息]
    D --> F[显示页面链接数量]

以上就是关于 BHO 和 Band 对象的详细介绍,希望能帮助开发者更好地扩展浏览器功能。

探索浏览器扩展:BHO与Band对象的实现与应用(续)

3. BHO与Band对象的实际应用案例分析

在实际开发中,BHO和Band对象有着广泛的应用场景,下面通过具体案例来进一步了解它们的实际用途。

3.1 BHO的实际应用
  • 广告拦截 :利用BHO捕获 DocumentComplete 事件,在页面加载完成后,通过分析页面的DOM结构,查找并移除广告元素。以下是一个简单的示例代码:
void Browser_DocumentComplete(object pDisp, ref object URL)
{
    if (pDisp == null || URL == null) return;
    IHTMLDocument2 document = (IHTMLDocument2)Browser.Document;
    if (document == null) return;

    // 查找并移除广告元素
    IHTMLElementCollection elements = document.all;
    for (int i = elements.length - 1; i >= 0; i--)
    {
        IHTMLElement element = (IHTMLElement)elements.item(i, 0);
        if (element.className != null && element.className.Contains("ad"))
        {
            element.parentNode.removeChild(element);
        }
    }
}
  • 页面性能监测 :在 BeforeNavigate2 事件中记录开始时间,在 DocumentComplete 事件中记录结束时间,计算页面加载时间。
DateTime startTime;
void Browser_BeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object  
    TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
{
    if (pDisp == null || URL == null) return;
    startTime = DateTime.Now;
}

void Browser_DocumentComplete(object pDisp, ref object URL)
{
    if (pDisp == null || URL == null) return;
    DateTime endTime = DateTime.Now;
    TimeSpan loadTime = endTime - startTime;
    MessageBox.Show("页面加载时间: " + loadTime.TotalSeconds + " 秒");
}
3.2 Band对象的实际应用
  • 自定义工具栏 :创建一个包含常用功能按钮的工具栏,如刷新、收藏、分享等。通过继承 BandObject 类,设置相应的静态成员和实现接口方法。
public class CustomToolbar : BandObject
{
    public CustomToolbar()
    {
        // 初始化工具栏按钮
        Button refreshButton = new Button();
        refreshButton.Text = "刷新";
        refreshButton.Click += RefreshButton_Click;
        this.Controls.Add(refreshButton);
    }

    private void RefreshButton_Click(object sender, EventArgs e)
    {
        if (WebBrowser != null)
        {
            WebBrowser.Refresh();
        }
    }

    public override void DefineMetadata()
    {
        ClassId = "{YOUR_CLASS_ID}";
        ProgId = "CustomToolbar";
        ObjectTitle = "自定义工具栏";
        ObjectName = "CustomToolbar";
        HelpText = "这是一个自定义工具栏";
        InitialSize = new Size(200, 30);
        MinSize = new Size(100, 30);
        MaxSize = new Size(500, 30);
        IntegralSize = new Size(10, 0);
        Style = BandObjectTypes.Toolbar;
    }
}
  • 侧边栏信息展示 :创建一个垂直资源管理器栏,用于展示网站的相关信息,如文章列表、热门标签等。
public class SidebarInfo : BandObject
{
    public SidebarInfo()
    {
        // 初始化侧边栏内容
        ListBox articleList = new ListBox();
        articleList.Items.Add("文章1");
        articleList.Items.Add("文章2");
        this.Controls.Add(articleList);
    }

    public override void DefineMetadata()
    {
        ClassId = "{YOUR_CLASS_ID}";
        ProgId = "SidebarInfo";
        ObjectTitle = "侧边栏信息";
        ObjectName = "SidebarInfo";
        HelpText = "展示网站相关信息";
        InitialSize = new Size(200, 400);
        MinSize = new Size(100, 200);
        MaxSize = new Size(300, 600);
        IntegralSize = new Size(10, 10);
        Style = BandObjectTypes.VerticalExplorerBar;
    }
}
4. 开发注意事项与技巧

在开发BHO和Band对象时,需要注意以下几点:
- 性能优化 :如前文所述,BHO的回调函数在IE UI线程中运行,应尽量减少处理时间,避免影响用户体验。可以采用异步处理或多线程的方式来处理复杂任务。
- 兼容性问题 :不同版本的IE可能对BHO和Band对象的支持有所不同,开发时需要进行充分的测试,确保在各种版本的IE中都能正常工作。
- 错误处理 :在代码中添加适当的错误处理机制,避免因异常情况导致浏览器崩溃或功能失效。

以下是一个简单的错误处理示例:

void Browser_DocumentComplete(object pDisp, ref object URL)
{
    try
    {
        if (pDisp == null || URL == null) return;
        IHTMLDocument2 document = (IHTMLDocument2)Browser.Document;
        if (document == null) return;
        MessageBox.Show("Total links on this page: " +
            document.links.length.ToString());
    }
    catch (Exception ex)
    {
        MessageBox.Show("发生错误: " + ex.Message);
    }
}
5. 总结与展望

BHO和Band对象为开发者提供了强大的浏览器扩展能力,通过捕获浏览器事件和扩展浏览器框架,可以实现各种个性化的功能。在未来的浏览器开发中,随着技术的不断发展,浏览器扩展的功能将更加丰富和强大。

以下是BHO和Band对象开发的步骤总结表格:
| 类型 | 开发步骤 |
| ---- | ---- |
| BHO | 1. 实现BHO类;2. 注册BHO;3. 捕获浏览器事件;4. 实现事件回调函数 |
| Band对象 | 1. 继承 BandObject 类;2. 设置静态成员元数据;3. 实现接口方法;4. 初始化UI内容 |

mermaid 流程图展示Band对象的开发流程:

graph LR
    A[创建Band对象类] --> B[设置静态成员元数据]
    B --> C[实现接口方法]
    C --> D[初始化UI内容]
    D --> E[注册Band对象]

通过本文的介绍,相信开发者对BHO和Band对象有了更深入的了解,能够在实际开发中灵活运用这些技术,为用户带来更好的浏览器体验。

【电能质量扰动】基于ML和DWT的电能质量扰动分类方法研究(Matlab实现)内容概要:本文研究了一种基于机器学习(ML)和离散小波变换(DWT)的电能质量扰动分类方法,并提供了Matlab实现方案。首先利用DWT对电能质量信号进行多尺度分解,提取信号的时频域特征,有效捕捉电压暂降、暂升、中断、谐波、闪变等常见扰动的关键信息;随后结合机器学习分类器(如SVM、BP神经网络等)对提取的特征进行训练分类,实现对不同类型扰动的自动识别准确区分。该方法充分发挥DWT在信号去噪特征提取方面的优势,结合ML强大的模式识别能力,提升了分类精度鲁棒性,具有较强的实用价值。; 适合人群:电气工程、自动化、电力系统及其自动化等相关专业的研究生、科研人员及从事电能质量监测分析的工程技术人员;具备一定的信号处理基础和Matlab编程能力者更佳。; 使用场景及目标:①应用于智能电网中的电能质量在线监测系统,实现扰动类型的自动识别;②作为高校或科研机构在信号处理、模式识别、电力系统分析等课程的教学案例或科研实验平台;③目标是提高电能质量扰动分类的准确性效率,为后续的电能治理设备保护提供决策依据。; 阅读建议:建议读者结合Matlab代码深入理解DWT的实现过程特征提取步骤,重点关注小波基选择、分解层数设定及特征向量构造对分类性能的影响,并尝试对比不同机器学习模型的分类效果,以全面掌握该方法的核心技术要点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值