1. BeforeNavigate2不发生

在C#中这个事件好像是有问题,一直没有被触发过。这个有可能是.NET Framework 4.0的bug,因为在C++中调用这个事件是有效的。
除了等微软发补丁,我们自己没什么解决办法。

2. 多个NavigateComplete2和DocumentComplete的问题
这个问题的一般结论是,在载入多个框架的网页时,每个框架都会引发自己的NavigateComplete2和DocumentComplete事件,判断该事件是否为主框架的对应事件可以用以下代码:

        void ieInstance_NavigateComplete2(object pDisp, ref object URL)        {            if (pDisp == ieInstance)            {                //Do something.            }        }
其中ieInstance为public对象,而SetSite中将其指定:
        public InternetExplorer ieInstance;

        ieInstance = (InternetExplorer)site;

可以认为是该IE窗口(或选项卡)对应的对象。

但是在某些复杂页面上,该事件似乎会被触发多次。在大部分网页上应该是只触发一次的。

3. 如何判断点击刷新按钮事件
其实我觉得Chrome的作法比较奇怪,在网页加载过程是不能刷新的,这个细节非常有趣。
因为我编写的BHO主要是设置网页元素事件,而这类事件会在刷新之后失效,因此我需要捕捉按刷新页面这个事件。
网页刷新过程中,NavigateComplete2和DocumentComplete都是不会发生的。同时IE并未提供这个按钮的事件,因此有很多不太正规的方法去判断。MSDN上说的是,如果一个DownloadBegin之前是DocumentComplete,那么该DownloadBegin应该是由刷新按钮触发的。
这个方法是不正确的,事实上我已经观测到很多网页在加载的过程中,DocumentComplete之后还有DownloadBegin。这多半是因为页面上有一些额外的元素,例如漂浮的图片广告之类。同时,该方法对于在加载过程中刷新,或者是刷新之后再刷新都是无效的。
我曾经用过一个方法,基于一个可能性较大的猜测:DownloadBegin必然有接下来的DownloadComplete,即使操作被挂起。那么,DownloadComplete之后呢?一般来说应该是紧接着一个新的DownloadBegin,如果没有,就是网页加载完毕了。据此,可以记录下每个DownloadComplete发生的时间,如果某一个DownloadBegin发生时,在其之前一定时间之内没有任何事件发生,即可以认为这个DownloadBegin是由刷新按钮触发的。
但是这个方法也有相当的缺陷,首先是间隔时间长度,设得太短容易误判,太长容易没反应,毕竟是基于人们浏览网页的习惯。此外,有一种特殊情况,就是在网页加载过程中刷新,很明显这种方法是不行的。
不过后来很意外,我发现网页元素在刷新后失效这个特性可以利用一下,具体的方法如下:
定义public变量:

        public IHTMLDocument3 document;        public HTMLElementEvents2_Event rootElementEvents = null;

在NavigateComplete2中将网页元素事件指定:

        document = ieInstance.Document as IHTMLDocument3;        rootElementEvents = document.documentElement as HTMLElementEvents2_Event;
在DownloadBegin中添加如下代码:
        if (rootElementEvents != document.documentElement as HTMLElementEvents2_Event)        {            //This might be refreshing, if no navigations.        }

该if语句就是判断rootElementEvents是否跟ieInstance挂钩,刷新之后既然不挂钩了,那么该判断为真时,就可以认为是用户刷新了网页。而为了使该判断仍然可以使用,之后需要在立刻在下一个DownloadComplete重新将二者挂钩。
该方法对任何时候的刷新都有效,但是有时在打开新页面时也会发生,可以通过一些小手段处理。

4. 避免网页元素事件的重复设定
用户打开一个选项卡之后,所进行的操作是难以估计的,有可能是重新打开该页面,刷新该页面(以上二者是不同的),从该选项卡打开新页面等等。一般来说,我们需要每次重新导航或者刷新之后,重新设定网页元素的事件。
正是因为IE没有刷新事件的接口,因此重新设定的适合时机不太容易抓住,前面所说的判断刷新的方法虽然有效,但是却不太容易将它与新的导航区分开来。而刷新和重导航是都需要设定事件的,这时就可能发生重复设定。
如果需要设定的事件并没有什么明显的操作,那很多时候倒也无关痛痒。但是如果操作是可见的,那么重复设定的后果就是可见操作会发生两次甚至更多次。例如在本例中,需要对鼠标的拖拽事件进行设定,可以拖拽出新的选项卡,那么重复设定就会导致一次拖拽出现两个甚至更多个新选项卡,这显然是我们不愿意看到的。
如果实在太难以区分,那么就干脆不要区分而采用其他的手段。在设定事件之前,首先清除前一个事件,即:

        rootElementEvents.ondragend -=            new HTMLElementEvents2_ondragendEventHandler(                Events_Ondragend);        rootElementEvents.ondragend +=            new HTMLElementEvents2_ondragendEventHandler(                 Events_Ondragend);
在设定之前首先清除,即可以保证事件只被设定一次,rootElementEvents应该是一个public的全局变量,而不是单属于这个函数。因为-=操作在相关事件没有设定的时候是不做操作,所以首次设定也不会有错误发生,该方法被证实是比较有效的。

C#编写IE插件的一些经验相关推荐

  1. 使用Qt编写模块化插件式应用程序

    动态链接库技术使软件工程师们兽血沸腾,它使得应用系统(程序)可以以二进制模块的形式灵活地组建起来.比起源码级别的模块化,二进制级别的模块划分使得各模块更加独立,各模块可以分别编译和链接,模块的升级不会 ...

  2. skywalking原理_Skywalking系列博客6手把手教你编写 Skywalking 插件

    点击上方 IT牧场 ,选择 置顶或者星标技术干货每日送达! 前置知识 在正式进入编写环节之前,建议先花一点时间了解下javaagent(这是JDK 5引入的一个玩意儿,最好了解下其工作原理):另外,S ...

  3. 编写OD插件将IDA中分析出来的函数名导入到OD中

    逆向程序的时候,喜欢用IDA静态分析,用OD动态调试,如果把IDA分析出来的函数名称都导入到OD中,调试的时候就知道哪些函数不需要再看了.以前我一直用GODUP的map loader,但是有些时候感觉 ...

  4. 使用Lua编写whireshark插件

    whireshark支持Lua.C.C++编写的插件 在这里,我简单介绍如何使用Lua编写whireshark插件. 一.插件的存放位置 whireshark插件分为个人插件和全局插件,在window ...

  5. 自己编写jQuery插件之表单验证

    自己编写jQuery插件之表单验证 吐个嘈先:最近状态不咋滴,真是什么都不想干,不想上班,做什么都没动力,觉得没意思.不想这样,不想这样,快让这种情绪消失吧,忽忽.... 表单验证在项目中用的还是比较 ...

  6. 如何编写 Nagios 插件 (http://zener.blog.51cto.com/937811/727685)

    如何编写 Nagios 插件 Nagios 的最激动人心的方面是可以轻松地编写您自己的插件,只需要了解一些简单的指导原则即可.为了管理插件,Nagios 每次在查询一个服务的状态时,产生一个子进程,并 ...

  7. maven插件编写_编写Maven插件的提示

    maven插件编写 最近,我花了很多时间为Maven编写插件或在其中工作. 它们简单,有趣且有趣. 我以为我会分享一些技巧,使编写它们时的生活更轻松. 提示1:将任务与Mojo分开 最初,您将把moj ...

  8. 编写Maven插件的提示

    最近,我花了很多时间来编写或为Maven开发插件. 它们简单,有趣且有趣. 我以为我会分享一些技巧,使他们在编写时变得更轻松. 提示1:将任务与Mojo分开 最初,您将把mojo的所有代码放入mojo ...

  9. 编写Eclipse插件教程–第1部分

    Eclipse是三个最受欢迎的Java开发IDE之一. 其成功的原因之一是其可扩展性. 对于任何知道该怎么做并且已经做到的人来说,编写eclipse插件都可以非常轻松快捷. 不幸的是,第一次在Ecli ...

  10. eval() python_如何使用 Python 编写 vim 插件

    前言 vim是个伟大的编辑器,不仅在于她特立独行的编辑方式,还在于她强大的扩展能力.然而,vim自身用于写插件的语言vimL功能有很大的局限性,实现功能复杂的插件往往力不从心,而且运行效率也不高.幸好 ...

最新文章

  1. docker添加jar包_Maven系列教材 (七)- 如何添加第三方jar包
  2. size_t与ssize_t
  3. 前端学PHP之面向对象系列第四篇——关键字
  4. MFC(WTL)编辑框长度限制
  5. [Everyday Mathematics]20150103
  6. 可以编辑vga格式文件的软件-PowerCreator Media Studio
  7. php异步查询数据库,php中mysql数据库异步查询实现
  8. Pandas.plot 做图
  9. 【操作系统学习笔记】操作系统基础
  10. 让菜鸟飞上天,简单搞定linux服务器
  11. 能源路由器 :分布式智能电网应用的混合通信体系结构
  12. 一文入门智能开关的3种功能形态
  13. steam邮箱登录教程
  14. WinSvr:在 Windows Server 中启用无线连接
  15. 声音和音频设备属性无法设置
  16. 疑似苹果平板电脑规格表曝光
  17. python中的if判断,和while循环的用法
  18. uni-app使用map组件开发map地图,获取后台返回经纬度进行标点
  19. 单片机 蓝牙/WIFI无线遥控智能家居系统设计
  20. 什么是RGB-D图像

热门文章

  1. [笔记分享] [SD] 块设备驱动学习小结
  2. 带weixin扫码登陆注册|仿城通网盘源码修复版
  3. 伺服电机常用参数设置_松下伺服电机一般都设置哪些参数
  4. 08cms cecore.cls.php,08CMS 变量覆盖导致getshell 等问题
  5. 使用CSS和HTML实现3D旋转魔方效果
  6. 传染病模型-java代码
  7. 三大抽样分布:卡方分布,t分布和F分布的简单理解
  8. 一博商业进销存管理系统 v2008 怎么用
  9. ss命令在linux上的安装
  10. 大妈钱太难赚,60余广场舞APP全军覆没