Saturday, May 14, 2011

C#编写IE插件的一些经验

1. BeforeNavigate2不发生

在C#中这个事件好像是有问题,一直没有被触发过。这个有可能是.NET Framework 4.0的bug,因为在C++中调用这个事件是有效的。

除了等微软发补丁,我们自己没什么解决办法。

2. 多个NavigateComplete2DocumentComplete的问题

这个问题的一般结论是,在载入多个框架的网页时,每个框架都会引发自己的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的全局变量,而不是单属于这个函数。因为-=操作在相关事件没有设定的时候是不做操作,所以首次设定也不会有错误发生,该方法被证实是比较有效的。

Wednesday, May 11, 2011

How to check the clicking of "Refresh button" in a Browser Help Object with C#

How to check the clicking of "Refresh button"

It is not a good experience.

In the versions of 0.9.2.x, the event handler was set many times at each "DownloadComplete". But in fact once is enough, too many times will reduce the loading speed indeed.

The reason is that we cannot catch the clicking of "Refresh button", I have no idea that why Microsoft never leave this interface, it is very bad.

Unexpectedly, I found this code is helpful:

//in NavigateComplete2 or other place:
document
= ieInstance.Document as IHTMLDocument3;
rootElementEvents
= document.documentElement as HTMLElementEvents2_Event;

Then when the refresh button is clicked:

//place this code in DownloadBegin
if (rootElementEvents != document.documentElement as HTMLElementEvents2_Event)
{
MessageBox.Show("You might click the refresh button just now");
}

The new tab and event handler

A new tab opened by clicking the URL (or clicking a URL with middle button, or right button then select "open in new tab"), cannot be set event handler in 'NavigateComplete2', but "DownloadComplete" is OK.

It is not right in "NotGood".

Conclusions

We can drop re-navigating, cut down the times of handler setting.


Super Drag and Go (0.9.5.0 beta) for IE9

超级拖拽插件(0.9.2.3 beta) for IE9

What's new:
0.9.2.2

You can still use "super drag" after refreshing the page.
In fact, the code has been written in 0.9.2.1, but was palced into a wrong position.
Additionally, the ZIP file for manually installation was bad, I have upload a right one to instead it.

更新在刷新页面之后仍可以使用拖拽。
其实实现这个功能的代码在0.9.2.1中已经写出来了,只是放错了位置,我在测试时也一直没注意到。此外,之前的手动安装文件是错误的,已经更正了。

0.9.2.3

Search string can be recognized by search engineering when language is not Simplified Chinese or English.

搜索字串可以在搜索引擎的设置非简体中文或英文时正确识别。

0.9.5.0

Re-navigating when open a new tab was removed. The times of handler setting was reduced.

修改了设置事件的方式,打开新选项卡不需要重新导航,设置事件的次数减到很少。


Tuesday, May 10, 2011

记念一些逐渐消失的软件

有些软件是我们以前安装电脑时必须首先考虑安装的,现在它们都很少见了。

随便写一点,记念一下这些软件。

 

Net Ants

作为多线程下载的开山鼻祖之一,Net Ants已经消失很久了,取代它的是FlashGet以及泛滥的迅雷。

至于后来者的优点,当然是更快。

CCED

在DOS时代曾经辉煌一时的CCED现在已经找不到了。最夸张的是它的主页现在乱得厉害。

Winamp

MP3的代名词,现在你还用它吗?

现在的播放软件都是些高大全的东西,比如微软的WMP,苹果的iTunes,还有啥?

金山游侠

游戏玩家必备。不过现在的游戏都有专用修改器??

KILL

公安部认证的杀毒软件,现在不知还更新不。

东方快车

Unicode是个好东西,于是转码软件失业了。

Monday, May 09, 2011

Super Drag and Go (Beta) for IE9

Super Drag and Go (Beta) for IE9
超级拖拽(beta) for IE 9

作者: s.weyl版本: 0.9.2.1 (beta)

如果你知道超级拖拽是什么,那么你可能需要这个插件。你可以用电子邮件向我查询或者索要源码(scarsty@gmail.com)。

1. 如何安装和卸载

首先需要你的系统中安装了.NET Framework 4.0 Client,可以在 http://www.microsoft.com/downloads/en/details.aspx?FamilyID=e5ad0459-cbcc-4b4f-97b6-fb17111cf544下载。根据微软的说法,完整的.NET框架是“Client”版的超集,所以我想.NET Framework 4.0也不成问题。

手动安装(推荐):
下载压缩包,解压到任意目录,以管理员身份运行附件中的“命令行”,切换到文件所在的目录,运行“install”。卸载的过程是类似的,只是要运行“uninstall”。
如果要在64位IE中使用,运行“install 64"和"uninstall 64”。
“CustomDrag.exe”这个程序可以对拖拽进行一些设置,还可以将自身添加到IE的工具菜单中。这些设置在卸载时都会被删除。

自动安装:
使用MSI文件可以自动安装,但是只有针对32位IE的安装文件。这时需要使用控制面板卸载。

2. 设置搜索字串:
用你喜欢的搜索引擎搜索“{0}”,然后把地址栏中的内容复制下来即可。

3. 参考文献:
http://www.cnblogs.com/TianFang/archive/2011/03/12/1982100.html
http://www.codeproject.com/KB/cs/Issuewithbandobjects.aspx
MSDN.
以及其他。

发布页:
http://code.google.com/p/cs-drag4ie9/

文件下载:
http://code.google.com/p/cs-drag4ie9/downloads/list

Tuesday, May 03, 2011

BHO事件的设置时机

每次导航设置,网页刷新或重导航需设置。

我想这个思路是不是有些问题。