介绍
大家都知道,在使用IE浏览页面时,经常需要下载一些文档和页面,我们可以选中连接然后点击右键菜单中的目标另存为…菜单,并弹出另存为对话框,我们可以将文件保存在指定目录下。见下图:

从IE6开始,我们可以编写自定义的扩展,截获目标另存为的动作,对下载进行更好地处理了。比如,IE的下载本身非常慢,那么我们可以注册一个下载扩展,对所有要通过另存下载的文件使用多线程下载,增加下载的速度。下面我们就来编写一个IE下载扩展,它的主要功能是禁止下载avi和mpg这类可能包含色情内容的文件。
创建下载扩展
新建一个ActiveX Library,保存为IEDown.dpr,然后新建一个COM组件,起名为TIEDownload,保存文件为CIEDownload.pas。一个下载扩展必须要实现IDownloadManager接口,由于Windows都是以C的头文件方式提供COM接口,而Borland无法及时的将所有的C的头文件翻译成Pascal的单元文件,因此VCL中并没有提供IDownloadMananger接口的声明,下面将使用的接口声明是Peter Larsen翻译的:
PBindInfo = ^TBindInfo; _tagBINDINFO = packed record cbSize: ULONG; szExtraInfo: LPWSTR; stgmedData: TStgMedium; grfBindInfoF: DWORD; dwBindVerb: DWORD; szCustomVerb: LPWSTR; cbstgmedData: DWORD; dwOptions: DWORD; dwOptionsFlags: DWORD; dwCodePage: DWORD; securityAttributes: TSecurityAttributes; iid: TGUID; pUnk: IUnknown; dwReserved: DWORD; end; TBindInfo = _tagBINDINFO; BINDINFO = _tagBINDINFO; IDownloadManager = interface(IUnknown) ['{988934A4-064B-11D3-BB80-00104B35E7F9}'] function Download( pmk: IMoniker; pbc: IBindCtx; dwBindVerb: DWORD; grfBINDF: DWORD; pBindInfo: PBindInfo; pszHeaders: PWidechar; pszRedir: PWidechar; uiCP: UINT): HRESULT; stdcall; end;
IDownloadManager接口只有一个Download方法,对于下载的操作来说,我们最关心的是无疑就是下载的Url了,在Download方法中有很多参数,其中的pmk参数是一个IMoniker接口。在COM中IMoniker接口主要是用来实现对象-名称智能绑定的,IMoniker的接口比较复杂,在这里就不详细讨论了,我们只需要知道通过调用IMoniker的GetDisplayName方法可以获得下载文件的Url就可以了。
下面是实现了IDownloadManager接口的TIEDownload的实现:
TIEDownload = class(TComObject, IDownloadManager) protected function Download( pmk: IMoniker; pbc: IBindCtx; dwBindVerb: DWORD; grfBINDF: DWORD; pBindInfo: PBindInfo; pszHeaders: PWidechar; pszRedir: PWidechar; uiCP: UINT): HRESULT; stdcall; end;function TIEDownload.Download(pmk: IMoniker; pbc: IBindCtx; dwBindVerb, grfBINDF: DWORD; pBindInfo: PBindInfo; pszHeaders, pszRedir: PWidechar; uiCP: UINT): HRESULT;var PUrl: PWidechar; Url:string;begin pmk.GetDisplayName(pbc, nil, PUrl); Url:=Trim(LowerCase(WideCharToString(PUrl))); //禁止下载avi和mpg文件 if (Pos('.avi', Url)=(Length(Url)-3)) or (Pos('.mpg', Url)=(Length(Url)-3))then begin ShowMessage('禁止下载Avi和Mpg文件'); Result:=S_OK; end else Result := E_NOTIMPL;end;
注意结果返回S_OK标识,表示下载扩展成功的进行了下载,而返回E_NOTIMPL时IE则认为下载扩展处理下载失败,会使用默认的下载功能来进行下载。
注册扩展
扩展的注册也很简单,只要设定注册表HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\ DownloadUI 关键字的值为自定义扩展的Guid的字符串形式就可以了。不过要注意的是IE目前最多只能注册一个下载扩展,不允许多个下载扩展同时并存。下面是实现注册功能的类工厂:
type TIEDownloadFactory = class(TComObjectFactory) public procedure UpdateRegistry(Register: Boolean); override; end; { TIEDownloadFactory } procedure TIEDownloadFactory.UpdateRegistry(Register: Boolean);begin inherited; if Register then CreateRegKeyValue(HKEY_CURRENT_USER, 'Software\Microsoft\Internet Explorer', 'DownloadUI', GuidToString(ClassId)) else DeleteRegKeyValue(HKEY_CURRENT_USER, 'Software\Microsoft\Internet Explorer', 'DownloadUI');end; initialization TIEDownloadFactory.Create(ComServer, TIEDownload, Class_IEDownload, 'IEDownload', '', ciMultiInstance, tmApartment);end.
注册扩展后,运行IE,打开光盘上和本程序同一个目录下的dowload.htm测试页面,在页面上有两个下载连接,一个是下载avi文件连接,一个是下载zip文件的连接,用右键菜单的另存为命令,会显示禁止操作消息界面,如下图,而下载zip文件则正常。

浙公网安备 33010602011771号