IE浏览器自定义地址协议的实现 本文关键词:自定义,浏览器,协议,地址
IE浏览器自定义地址协议的实现 本文简介:IE浏览器自定义地址协议的实现http://hi.baidu.com/widebright/item/b77c3619d99cdb17e2f98651IE浏览器自定义地址协议的实现bywidebright关键字:IE插件,shell接口编程,自定义IE协议,VC2003ATL实现COM浏览QQ空间的
IE浏览器自定义地址协议的实现 本文内容:
IE浏览器
自定义地址协议的实现
http://hi.baidu.com/widebright/item/b77c3619d99cdb17e2f98651
IE浏览器
自定义地址协议的实现
by
widebright
关键字:IE插件,shell接口编程,自定义IE协议,VC2003
ATL
实现COM
浏览QQ空间的时候发现,只要在IE地址中输入象一下这种形式的地址,
tencent://Message/?Uin=251464630
//
CWidebrightBlog
[
coclass,threading(“apartment“),vi_progid(“UrlSearchHook.WidebrightBlog“),progid(“UrlSearchHook.WidebrightBlog.1“),version(1.0),uuid(“44AA49F1-7E20-472E-A5A4-08D3233D9132“),helpstring(“WidebrightBlog
Class“)
]
class
ATL_NO_VTABLE
CWidebrightBlog
:
public
IWidebrightBlog,public
IURLSearchHook
{
public:
CWidebrightBlog()
{
//
MessageBox(NULL,“在CWidebrightBlog()“,“widebright
“,MB_OK);
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
//组件接口映射部分,该部分映射主要是告诉QueryInterface能返回哪些接口给外部
BEGIN_COM_MAP(CWidebrightBlog)
COM_INTERFACE_ENTRY(IWidebrightBlog)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IURLSearchHook)
END_COM_MAP()
HRESULT
FinalConstruct()
{
return
S_OK;
}
void
FinalRelease()
{
}
public:
STDMETHODIMP
Translate(
LPWSTR
lpwszSearchURL,DWORD
cchBufferSize)
{
//
MessageBox(NULL,“在Translate函数中了“,“widebright
“,MB_OK);
if
(wcsncmp(L“widebright“,lpwszSearchURL,10
)==0)
{
//
MessageBox(NULL,“找到了“,“widebright
“,MB_OK);
wcscpy(lpwszSearchURL,L“http://hi.baidu.com/widebright“);
return
S_OK
;
}
return
E_FAIL;
//没有修改lpwszSearchURL
return
S_FALSE;
//修改了lpwszSearchURL的,但还需要继续处理
}
int
MyFunction(void)
//这个是自己利用向导生成Method的函数,想试一下COM接口,没什么用的,根本程序无关。
{
return
0;
}
};
不过编译一下,有错,说是IURLSearchHook接口GUID没定义,明显是有这个接口的,在MSDN里面没有什么说明,最后在CSDN上找到一张帖子
,说是VC2003里面
和VC6的ATL不同,在VC6里面上面代码是可以通过的,但在VC2003以后版本就不行了。这是引用帖子中原话“There
are
two
header
files
in
VC.NET,one
in
Vc7/include
and
the
other
in
Vc7/PlatformSDK/include.
The
former
splits
off
the
smart
pointer
typedefs
into
comdefsp.h,and
it
doesn
t
include
IContextMenu.
The
latter
does.
You
can
try
to
#include
the
PlatformSDK
header
directly,change
your
INCLUDE
path
order,or
supply
the
missing
typedef
yourself,e.g.
struct
__declspec(uuid(“000214e4-0000-0000-c000-000000000046“))
IContextMenu;
_COM_SMARTPTR_TYPEDEF(IContextMenu,__uuidof(IContextMenu));”
我查看了VC目录下的两个文件也确实如此,所以手工添加了一下Include路径确保#include
包含的是Platform中的那个comdef.h就行了。在
UrlSearchHook工程-“工程属性”-》“C/C++”
-》
“附加包含目录”
属性,增加一个
“C:/Program
Files/Microsoft
Visual
Studio
.NET
2003/Vc7/PlatformSDK/Include“。
然后再编译就通过了,生成了dll文件,整个代码很简单,就是实现IURLSearchHook接口的
Translate函数,BEGIN_COM_MAP和
COM_INTERFACE_ENTRY几个ATL宏声明IURLSearchHook接口外部可见,就一些ok了。
不过要让IE知道有这个URL
Search
Hook扩展,还要修改注册表才行。我手工在HKEY_CURRENT_USER/Software/
Microsoft/
Internet
Explorer/
UrlSearchHooks
添加了一项
REG_SZ类型名字为{44AA49F1-7E20-472E-A5A4-08D3233D9132}
的项,其中名字和你生成的dll注册类型对应
,在上面代码里也可以看到。注意的是MSDN上说的是HKEY_LOCAL_MACHINE//
注册表位置,但其他文档说得是HKEY_CURRENT_USER位置,而且我在HKEY_LOCAL_MACHINE下也没看到UrlSearchHooks项,不知道添加在HKEY_LOCAL_MACHINE会不会有效果,不过添加在HKEY_CURRENT_USER/Software/
Microsoft/
Internet
Explorer/
UrlSearchHooks会成功就是了。(建在HKEY_LOCAL_MACHINE/Software/
Microsoft/
Internet
Explorer/
UrlSearchHooks
下面可以的,如果没有UrlSearchHooks
下就自己创建一个,然后建一个REG_SZ类似的值,名字指定为你的插件的GUID的值就行了
widebright
2008-04-22)
好了,启动IE7,输入widebright开头的地址,都跳到http://hi.baidu.com/widebright
来了,
在卡卡上网助手里可见
CWidebrightBlog
Object
地址栏搜索
项
。
方法三:
也是使用IE扩展接口实现,我之所以把它独立处理列为一种方法,是我觉得是一种很使用的价值的功能。我发现电脑里面有的电子书在我升级到IE7后看不了,可能也是这方面有问题。在注册表中都可见到这些Ebook电子书的注册值,可能Ebook也就是这么干的吧。
更多相关内容搜索:协议插件(Asynchronous
Pluggable
Protocols),MIME
Filter
我是在下面这篇文章里面发现这种实现方法的,下面转载:
转贴
来互联网
,不过文章作者倒是很眼熟,好像是看过他几篇文章了,支持!
IE异步可插入协议扩展
作者
陈省
介绍
对于每天都要使用的IE浏览器的人来说,输入www.16fw.com
等网址进行网上冲浪就象呼吸一样自然。大多数情况时,我们可能根本想不起来要在网址前面加上http://
来声明要访问的是一个基于http协议的Web网站。所谓网络协议,其实无非就是一组描述如何获取不同资源并进行通讯的行为规则。IE浏览器除了内置了对
http协议外,还持ftp和gopher等协议。
从IE4开始,IE允许通过插入式异步协议扩展来扩展它处理协议的功能,人们可以通过自定义的扩展来让IE支持更多的协议,比如一些不是普遍支持的流媒体协议等。此外,我们还可以通过插入式协议扩展让IE可以以HTML文件的形式显示一个数据库中的表。
异步可插入协议的原理
可插入式协议是基于异步的URL
Moniker技术的。Moniker最早是从OLE2中引入的概念,当时的Moniker就是一个COM绑定和定位对象,人们可以使用Moniker来定位并加载被保存到文件中的COM组件,实现COM的可持续性,一开始Moniker是基于同步方式实现的。随着网络技术的发展,定位并从网络上获取信息的需求逐渐超过了对本地数据的存取需求,因为网络的通讯通常都是不稳定的,因此需要以异步的方式来实现。为此微软设计了URL
moniker对象来提供网络信息下载过程的一个统一接口,基于URL来访问网络资源的Moniker演变成了以异步方式实现的Moniker。
IE的URL
moniker是在urlmon.dll动态连接库中实现的。当urlmon.dll处理http,ftp,Gopher等内置协议的访问时,它把访问请求转发给内部的一个COM组件来处理,该COM组件使用WinInet函数来完成实际的处理工作。对于非内置的协议,urlmon.dll则把请求转发给特定的可插入协议扩展进行处理,比如说mailto:协议。
一个典型的异步可插入协议(APP)的主要工作的就是接收一个非IE内置的UrlURL协议字符串,对字符串进行解析,分析字符串的元素,并根据协议访问相应的系统或者网络资源,并将网络资源的内容输出到浏览器。
一个自定义的电子书可插入协议的实现
我平时业余时间喜欢上网上找一些娱乐小说和技术书籍来看,其中有一些小说采用的是付费方式才能看既然是付费的小说,自然会提供一些加密的方式,避免盗版书在网上的传播。
接下来,我想写一个程序对一些Html文件进行加密,只有用户在浏览器中键入EBook://c:/abc.htm,然后输入口令后,才能看到解密后的Html页面。接下来,就看如何使用APP来实现这样一个可插入协议。
创建COM组件
首先,新建一个ActiveX
Library项目,保存为IEProtocol.dpr,然后新建一个名为TIEEncryptAPP的COM组件,保存为
CIEProtocol.pas文件。一个APP组件至少要实现IInternetProtocol接口(该接口定义在urlmon.pas单元中),又由于IInternetProtocol接口派生自IInternetProtocolRoot,所以我们还需要实现
IInternetProtocolRoot接口。下面是实现了IInternetProtocol接口的TIEEncryptAPP类的定义:
type
TIEEncryptAPP
=
class(TComObject,IInternetProtocol)
protected
//IInternetProtocolRoot接口定义
function
Start(szUrl:
LPCWSTR;
OIProtSink:
IInternetProtocolSink;
OIBindInfo:
IInternetBindInfo;
grfPI,dwReserved:
DWORD):
HResult;
stdcall;
function
Continue(const
ProtocolData:
TProtocolData):
HResult;
stdcall;
function
Abort(hrReason:
HResult;
dwOptions:
DWORD):
HResult;
stdcall;
function
Terminate(dwOptions:
DWORD):
HResult;
stdcall;
function
Suspend:
HResult;
stdcall;
function
Resume:
HResult;
stdcall;
//IInternetProtocol接口定义
function
Read(pv:
Pointer;
cb:
ULONG;
out
cbRead:
ULONG):
HResult;
stdcall;
function
Seek(dlibMove:
LARGE_INTEGER;
dwOrigin:
DWORD;
out
libNewPosition:
ULARGE_INTEGER):
HResult;
stdcall;
function
LockRequest(dwOptions:
DWORD):
HResult;
stdcall;
function
UnlockRequest:
HResult;
stdcall;
end;
其中IInternetProtocolRoot接口的方法意义如下:
Abort
停止一个正在进行的资源下载过程
Continue
允许协议扩展继续进行进行资源数据下载过程。
Resume
未来扩充需要,暂时未实现。
Start
启动同该协议相关的资源下载过程。
Suspend
未来扩充需要,暂时未实现
Terminate
结束下载过程,释放扩展分配的资源。
而IInternetProtocol协议的方法定义如下:
LockRequest
锁定资源下载请求,这时IInternetProtocolRoot接口的Terminate方法将允许被调用,与此同时未下载完的数据仍然可以被读取。
Read
浏览器调用这个方法从协议扩展获得相应的数据。
Seek
移动读取数据的位置。
UnlockRequest
释放请求锁定
对于电子图书这样一个简单的协议扩展来说,我们只需要实现Start方法来启动下载过程,并通过Read方法向浏览器返回解密后的电子图书的数据就可以了。其它的方法只要简单的返回请求结果,而无须做任何的操作:
function
TIEEncryptAPP.Abort(hrReason:
HResult;
dwOptions:
DWORD):
HResult;
begin
Result
:=
Inet_E_Invalid_Request;
end;
function
TIEEncryptAPP.Continue(
const
ProtocolData:
TProtocolData):
HResult;
begin
Result
:=
Inet_E_Invalid_Request;
end;
function
TIEEncryptAPP.LockRequest(dwOptions:
DWORD):
HResult;
begin
Result
:=
S_OK;
end;
function
TIEEncryptAPP.Resume:
HResult;
begin
Result
:=
Inet_E_Invalid_Request;
end;
function
TIEEncryptAPP.Seek(dlibMove:
LARGE_INTEGER;
dwOrigin:
DWORD;
out
libNewPosition:
ULARGE_INTEGER):
HResult;
begin
Result
:=
E_Fail;
end;
function
TIEEncryptAPP.Suspend:
HResult;
begin
Result
:=
Inet_E_Invalid_Request;
end;
function
TIEEncryptAPP.Terminate(dwOptions:
DWORD):
HResult;
begin
Result
:=
S_OK;
end;
function
TIEEncryptAPP.UnlockRequest:
HResult;
begin
Result
:=
S_OK;
end;
启动协议处理
首先来看如何启动协议处理,当我们在浏览器中输入EBook://c:/ebook.htm字符串想要浏览加密的页面文件时,IE会找到EBook的扩展协议,然后调用协议的Start方法来启动协议处理过程:
threadvar
ResultHTML:
array[064
1024
-
1]
of
Char;
{
64
kB
}
CurrPos:
Integer;
BytesLeft:
Integer;
ProtSink:
IInternetProtocolSink;
function
TIEEncryptAPP.Start(szUrl:
LPCWSTR;
OIProtSink:
IInternetProtocolSink;
OIBindInfo:
IInternetBindInfo;
grfPI,dwReserved:
DWORD):
HResult;
Const
ErrorHTML
=
#13+
浏览电子书%s时发生错误
#13+
%s
#13+
;
var
S:
string;
begin
S
:=
WideCharToString(szURL);
{
EBook://
}
Delete(S,1,8);
//去掉后面/符号
SetLength(S,Length(S)
-
1);
S
:=
HTTPDecode(S);
if
FileExists(S)
then
begin
//显示密码提示框
if
InputBox(
密码,请输入密码,)
hubdog
then
S:=Format(ErrorHTML,[S,无效的密码
])
else
S
:=
Decrypt(S);
end
else
S
:=
Format(ErrorHTML,[S,没有找到文件
]);
CurrPos
:=
0;
BytesLeft
:=
Length(S);
FillChar(ResultHTML,SizeOf(ResultHTML),0);
StrPCopy(ResultHTML,S);
ProtSink
:=
OIProtSink;
//数据通知
OIProtSink.ReportData(bscf_LastDataNotification,0,BytesLeft);
//数据可完全获得的通知
OIProtSink.ReportData(bscf_DataFullyAvailable,0,BytesLeft);
Result
:=
S_OK;
end;
Start方法中有一个szUrl的参数,对应着我们在浏览器中输入的url字符串(注意:IE会在输入的字符串末尾自动加上一个斜杠),为了获得要处理的被加了密的html文件,使用Delete函数先从字符串中删除EBook://8个字符,然后在用SetLength去掉IE添加的斜杠,同时要注意IE传过来的字符串参数是进行Http编码的,所以还要调用HttpApp单元中的HttpDecode来进行解码还原为c:/ebook.htm的文件名字符串。
如果输入的文件存在的话,则提示用户输入密码,如果密码匹配的话,则调用Decrypt函数对文件进行解密并,返回解密后的文本串。如果文件不存在,或者密码不匹配,则生成ErrorHtml返回一个错误描述的HTML页面。关于加密和解密过程,比较简单,我会在后面介绍。
获得解密后的文本后,将文本内容复制到ResultHTML字符串缓冲区中(这里的缓冲区处于简单的考虑,写死成64K)。另外要注意的是这里用的参数都使用ThreadVar来声明,这是因为协议处理过程是一个多线程异步的过程,同一时刻,可能有多个EBook的协议请求在处理中,所以变量都要声明为线程安全的,以避免资源冲突。接下来保存IE通过Start方法传过来的OIProtSink协议处理事件接口(稍后还会用到),然后调用接口的ReportData方法通知IE要获取的数据量为BytesLeft,并通过设定ReportData的grfBSCF参数为LastDataNotification
和DataFullyAvailable通知IE,数据已经完全准备好了,这样稍后IE就会调用扩展的Read方法来获得解密后的页面数据。
返回解密数据
function
TIEEncryptAPP.Read(pv:
Pointer;
cb:
ULONG;
out
cbRead:
ULONG):
HResult;
var
I:
Integer;
begin
if
(BytesLeft
>
0)
then
begin
I
:=
CB;
if
(I
>
BytesLeft)
then
I
:=
BytesLeft;
Move(ResultHTML[CurrPos],PV^,I);
CBRead
:=
I;
Dec(BytesLeft,I);
Inc(CurrPos,I);
Result
:=
S_OK;
{通知IE读取更多的数据
}
end
else
begin
//数据全部下载完成
Result
:=
S_False;
ProtSink.ReportResult(S_OK,0,nil);
end;
end;
在Read
方法中,IE会传过来一个内部缓冲区的指针pv,同时cb参数表示缓冲区的大小,电子书的数据有可能会很大,而IE的缓冲区不会无限大,因此IE会分多次来读取电子书的数据,我们每次应该尽可能读取cb大小的数据,将其移动到IE的缓冲区内,读取完成后减少BytesLeft的值,同时增加CurrPos
的值来记录当前以发送给IE的数据位置,并返回cbRead告诉IE传送的数据到底有多少。如果一次没有返回全部的数据,则返回S_OK通知IE还有没传送完的数据,这样IE就会继续调用Read方法来完成数据下载,最后当所有的数据都处理完毕后,则返回S_False通知IE已经没有要传的数据了,同时,调用事件接口ProtSink的ReportData方法通知IE,协议处理完毕。
加密解密
还是为了简单起见,html页面的加密非常简单,我使用XOR加密,这样的好处是,处理简单。因为XOR加密和解密是一个可逆过程,加密和解密使用同一个函数就可以完成了。下面是加密和解密字符串类:
type
//加密字符串类
TEncryptStrings
=
class(TStringList)
public
procedure
SaveToStream(Stream:
TStream);
override;
end;
//解密字符串类
TDecryptStrings
=
class(TStringList)
public
procedure
LoadFromStream(Stream:
TStream);
override;
end;
implementation
//用xor算法进行加密
procedure
EncodeStream(Input,Output:
TStream);
var
InBuf:
array[01023]
of
byte;
BufPtr:
PChar;
I,BytesRead:
Integer;
begin
Assert(Assigned(Input),无效的流指针
);
//必须重新设置流指针位置
Input.Position
:=
0;
Output.Position
:=
0;
repeat
BytesRead
:=
Input.Read(InBuf,SizeOf(InBuf));
I
:=
0;
while
I
<
BytesRead
do
begin
InBuf[I]
:=
InBuf[I]
xor
8;
Inc(I);
end;
OutPut.Write(InBuf,BytesRead);
until
BytesRead
=
0;
Input.Position
:=
0;
Output.Position
:=
0;
end;
{
TDecryptStrings
}
procedure
TDecryptStrings.LoadFromStream(Stream:
TStream);
var
OutStream:TMemoryStream;
begin
//解密
OutStream:=TMemoryStream.Create;
try
EncodeStream(Stream,OutStream);
inherited
LoadFromStream(OutStream);
finally
OutStream.Free;
end;
end;
{
TEncryptStrings
}
procedure
TEncryptStrings.SaveToStream(Stream:
TStream);
var
OutStream:
TMemoryStream;
begin
inherited;
//加密
OutStream
:=
TMemoryStream.Create;
try
EncodeStream(Stream,OutStream);
Stream.CopyFrom(OutStream,0);
finally
OutStream.Free;
end;
end;
为了减少编码工作量,我直接从TStringList类派生了两个字符串列表处理类,并重载了LoadFromStream和SaveToStream方法来对流进行加解密处理。加解密处理都是调用的EncodeStream方法来对字符串流进行加密,加密使用每个字符同8进行xor运算。
下面我写了一个程序,可以对html文件进行处理点击Button1,则将文件进行加密处理,点击Button2可以对察看解密后文件的原有内容:
procedure
TForm1.Button1Click(Sender:
TObject);
var
Strings:TEncryptStrings;
begin
if
not
OpenDialog1.Execute
then
Exit;
Strings:=TEncryptStrings.Create;
try
Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
Strings.Text:=Memo1.Text;
Strings.SaveToFile(OpenDialog1.FileName);
Memo2.Lines.LoadFromFile(OpenDialog1.FileName);
finally
Strings.Free;
end;
end;
procedure
TForm1.Button2Click(Sender:
TObject);
var
Strings:TDecryptStrings;
begin
if
not
OpenDialog1.Execute
then
Exit;
Strings:=TDecryptStrings.Create;
try
Memo1.Lines.LoadFromFile(OpenDialog1.FileName);
Strings.LoadFromFile(OpenDialog1.FileName);
Memo2.Lines.Text:=Strings.Text;
finally
Strings.Free;
end;
end;
界面如下:
注册扩展
完成了扩展协议后,只剩下注册扩展了,要想注册扩展,需要在注册表的HKEY_CLASSES_ROOT/PROTOCOLS/Handler/下添加EBook关键字,然后在该关键字下添加名为CLSID的字段,设定其值为扩展的Guid,下面是用于注册的类工厂:
type
TIEEncryptAPPFactory
=
class(TComObjectFactory)
public
procedure
UpdateRegistry(Register:
Boolean);
override;
end;
{
TIEEncryptAPPFactory
}
procedure
TIEEncryptAPPFactory.UpdateRegistry(Register:
Boolean);
begin
inherited;
if
Register
then
CreateRegKeyValue(HKEY_CLASSES_ROOT,PROTOCOLS/Handler/EBook,CLSID,GuidToString(ClassID))
else
DeleteRegKeyValue(HKEY_CLASSES_ROOT,PROTOCOLS/Handler/EBook,CLSID
);
end;
initialization
TIEEncryptAPPFactory.Create(ComServer,TIEEncryptAPP,Class_IEEncryptAPP,IEEncryptAPP,,ciMultiInstance,tmApartment);
end.
最后,将本书光盘中的ebook.htm文件放到c:根目录下,注册扩展后,启动IE,输入ebook://c:/ebook.htm,然后在弹出的密码框中输入hubdog,IE就会显示解密后的电子小说,界面示意如下:
临时注册扩展
上面的注册方法可以称为持久注册的方法,一旦注册就总是生效,。IE还提供临时注册的方法,只要编写一个BHO扩展,在BHO加载时,调用TemporyRegister方法进行注册,在IE退出时调用:
var
Factory:IClassFactory;
procedure
TemporaryRegister;
begin
CoGetClassObject(Class_IEEncryptAPP,CLSCTX_SERVER,nil,IClassFactory,Factory);
CoInternetGetSession(0,InternetSession,0);
InternetSession.RegisterNameSpace(Factory,Class_IEEncryptAPP,EBook,0,nil,0);
end;
procedure
UnRegister;
begin
InternetSession.UnregisterNameSpace(Factory,EBook
);
end;
这样的好处是,在程序运行时,可以随时解除对扩展协议的支持,而前面的永久注册法必须在解除注册后,重新启动IE才行。缺点是必须通过一个BHO来实现临时注册。
其它的APP
除了上面的协议扩展外,IE还支持NameSpace
Handler以及Mime-Handler两种APP扩展。其中NameSpace扩展是对特定名字空间进行处理的协议扩展,比如如果我们注册一个对名字空间,则当IE处理http://hubdog.csdn.net、的URL
时,一旦遇到hubdog名字空间,就会调用我们的NameSpace
Handler进行处理,而不管URL是基于http协议的还是ftp等其它协议的都进行处理。从实现的角度来看,NameSpace的实现方法和前面的协议扩展几乎一样,除了注册时要填写的注册表项内容不同而已。
而Mime协议扩展处理的主要是对一些特殊的媒体资源如图片,声音文件进行处理,比如下表是IE默认支持的一些媒体形式。
text/richtext
text/html
audio/x-aiff
audio/basic
audio/wav
image/gif
image/jpeg
…
如果那天哪天你发明一种新的音乐形式,比如扩展名为.sy,就可以注册一个Mime扩展对
.sy文件处理,让IE播放相应的声音。
Mime扩展除了需要支持IInternetProtocol接口外,还必须实现IInternetProtocolSink接口,接口定义如下:
IInternetProtocolSink
=
interface
[
{79eac9e5-baf9-11ce-8c82-00aa004ba90b}
]
function
Switch(const
ProtocolData:
TProtocolData):
HResult;
stdcall;
function
ReportProgress(ulStatusCode:
ULONG;
szStatusText:
LPCWSTR):
HResult;
stdcall;
function
ReportData(grfBSCF:
DWORD;
ulProgress,ulProgressMax:
ULONG):
HResult;
stdcall;
function
ReportResult(hrResult:
HResult;
dwError:
DWORD;
szResult:
LPCWSTR):
HResult;
stdcall;
end;
数据通讯方式上来看,Mime扩展同一般的协议扩展差别比较大,通讯的流程是这样的:
1.
首先,IE会在遇到相应资源下载请求时,调用扩展的Start方法来启动下载过程。
2.
然后IE会调用扩展的ReportProgress方法,告知扩展被下载的数据保存的缓存文件名称。
3.
当IE下载完原始数据后,会调用扩展的ReportData方法通知扩展准备对原始数据进行加工处理。
4.
这时,扩展需要调用IE提供的IInternetProtocol接口的Read方法来获得原始数据。
5.
对原始数据处理后,扩展要调用IE的IInternetProtocolSink接口的ReportData方法通知IE数据处理完毕。
6.
最后,IE调用扩展的Read方法获得处理后的数据。
可以看出来同一般协议扩展的纯主动向IE返回数据的方式不同,Mime的数据通讯方式即有被动的接收IE获取的原始数据,也有将处理后的数据返回IE的主动通讯方式。
由于本质上来看,Mime同一般的APP的实现相差不多,所以这里我将不再浪费篇幅来给出Mime扩展的实现实例了。
IE早已经不再是一个单纯意义的Web浏览程序了,通过对IE支持的协议扩充,我们可以将IE变成一个网络开发平台,可以将IE的功能无限延伸。
Trackback:
http://tb.blog.csdn.net/TrackBack.aspx?PostId=1376137
篇2:松果游戏浏览器软件介绍
松果游戏浏览器软件介绍 本文关键词:松果,软件介绍,浏览器,游戏
松果游戏浏览器软件介绍 本文简介:松果游戏浏览器唯一正版官网:http://www.16fw.com/松果游戏浏览器软件介绍l工具简介松果游戏浏览器是一款专门为网页游戏玩家研发的页游浏览器,于2012年10月11号正式上线!玩家不仅可以在松果游戏浏览器上找到页游浏览器所应包括的一些基本功能,如游戏加速,账号多开,老板键,页面静音和
松果游戏浏览器软件介绍 本文内容:
松果游戏浏览器唯一正版官网:http://www.16fw.com/
松果游戏浏览器软件介绍
l
工具简介
松果游戏浏览器是一款专门为网页游戏玩家研发的页游浏览器,于2012年10月11号正式上线!玩家不仅可以在松果游戏浏览器上找到页游浏览器所应包括的一些基本功能,如游戏加速,账号多开,老板键,页面静音和热键设置等,而且还可以找到并只能在松果游戏浏览器上找到由特约作者专门为各款当前热门网页游戏所研发的工具。
轻松游戏、释放双手、高速畅玩、稳定加速、海量应用、热游精选、优化页游等,通过使用松果游戏浏览器所提供的这些页游工具,玩家可以从游戏繁琐枯燥的操作中释放出来,享受更轻松,自由的游戏体验,更合理的安排游戏时间!
l
最新支持网页游戏列表
1.
神曲游戏工具;
2.
龙将游戏工具;
3.
名将传说游戏工具;
4.
火影世界游戏工具;
5.
惊天战神游戏工具;
6.
神仙道游戏工具;
7.
盛世三国游戏工具。
8.
凡人修真2游戏工具;
9.
神魔遮天游戏工具;
10.
傲视遮天游戏工具;
11.
热血海贼王游戏工具;
12.
神魔仙界游戏工具;
13.
仙落凡尘游戏工具。
请访问松果官网获取更多海量精品游戏工具!
l
松果游戏浏览器更新日志
2012年11月
版本信息:1.1正式版
(目前最新版本)
更新时间:2012-10-31
解决BUG
--点击静音按钮闪屏问题
--升级页面框内容重叠问题
--神魔遮天游戏工具界面问题
新增功能
--新增游戏工具快捷按钮
--新增收藏夹功能
优化功能
--优化工具栏界面布局
2012年10月
2.
版本信息:1.00.7839
更新时间:2012-10-11
解决BUG
--二级页记录重复问题
--浏览器错误弹出问题
--托盘图标提示乱码信息问题
--多进程老板键问题
--游戏工具页面拖动问题
新增功能
--默认页页面改版
--二级页新增游戏推荐平台
--二级页新增游戏广告列表
优化功能
--优化浏览器效率
2012年8月
3.
版本信息:1.02.7487
更新时间:2012-8-22
解决BUG
--解决按桌面快捷键页面显示黑框问题
--解决内容文本框复制黏贴的问题
--解决收藏夹删除报错问题
--解决关闭标签页提示信息问题
新增功能
--新增默认页打开二级页功能
--优化游戏工具界面及流程
4.
版本信息:1.01.7323
更新时间:2012-8-14
解决BUG
界面--
解决各个主题下软件界面的兼容性问题
托盘--
新增托盘图标右键菜单
标题栏--
新增反馈意见功能
加速--
解决游戏加速上线限制问题
--
解决游戏工具页面自动隐藏问题
--
解决当前激活页滚轮滚动问题
--
解决任务栏点击切换问题
--
解决点击收藏夹崩溃的问题
在使用松果游戏浏览器时如遇到任何问题,您可以访问松果官网并联系在线客服。
6