介绍
大家都知道,在使用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文件则正常。