介绍

 

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

posted on 2009-08-28 22:42  on_road  阅读(1163)  评论(0编辑  收藏  举报