unit FileDownLoadThread; interface uses Classes, SysUtils, Windows, ActiveX, UrlMon; const S_ABORT = HRESULT($80004004); type TFileDownLoadThread = class; TDownLoadProcessEvent = procedure(Sender: TFileDownLoadThread; Progress, ProgressMax: Cardinal) of object; TDownLoadCompleteEvent = procedure(Sender: TFileDownLoadThread) of object; TDownLoadFailEvent = procedure(Sender: TFileDownLoadThread; Reason: LongInt) of object; TDownLoadMonitor = class(TInterfacedObject, IBindStatusCallback) private FShouldAbort: Boolean; FThread: TFileDownLoadThread; protected function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; stdcall; function GetPriority(out nPriority): HResult; stdcall; function OnLowResource(reserved: DWORD): HResult; stdcall; function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult; stdcall; function OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult; stdcall; function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult; stdcall; function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc: PFormatEtc; stgmed: PStgMedium): HResult; stdcall; function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResult; stdcall; public constructor Create(AThread: TFileDownLoadThread); property ShouldAbort: Boolean read FShouldAbort write FShouldAbort; end; TFileDownLoadThread = class(TThread) private FSourceURL: string; FSaveFileName: string; FProgress, FProgressMax: Cardinal; FOnProcess: TDownLoadProcessEvent; FOnComplete: TDownLoadCompleteEvent; FOnFail: TDownLoadFailEvent; FMonitor: TDownLoadMonitor; protected procedure Execute; override; procedure UpdateProgress(Progress, ProgressMax, StatusCode: Cardinal; StatusText: string); procedure DoUpdateUI; public constructor Create(ASrcURL, ASaveFileName: string; AProgressEvent: TDownLoadProcessEvent = nil; ACompleteEvent: TDownLoadCompleteEvent = nil; AFailEvent: TDownLoadFailEvent = nil; CreateSuspended: Boolean = False); property SourceURL: string read FSourceURL; property SaveFileName: string read FSaveFileName; property OnProcess: TDownLoadProcessEvent read FOnProcess write FOnProcess; property OnComplete: TDownLoadCompleteEvent read FOnComplete write FOnComplete; property OnFail: TDownLoadFailEvent read FOnFail write FOnFail; end; implementation constructor TDownLoadMonitor.Create(AThread: TFileDownLoadThread); begin inherited Create; FThread := AThread; FShouldAbort := False; end; function TDownLoadMonitor.GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult; begin result := S_OK; end; function TDownLoadMonitor.GetPriority(out nPriority): HResult; begin Result := S_OK; end; function TDownLoadMonitor.OnDataAvailable(grfBSCF, dwSize: DWORD; formatetc: PFormatEtc; stgmed: PStgMedium): HResult; begin Result := S_OK; end; function TDownLoadMonitor.OnLowResource(reserved: DWORD): HResult; begin Result := S_OK; end; function TDownLoadMonitor.OnObjectAvailable(const iid: TGUID; punk: IInterface): HResult; begin Result := S_OK; end; function TDownLoadMonitor.OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult; begin if FThread <> nil then FThread.UpdateProgress(ulProgress, ulProgressMax, ulStatusCode, ''); if FShouldAbort then Result := E_ABORT else Result := S_OK; end; function TDownLoadMonitor.OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; begin Result := S_OK; end; function TDownLoadMonitor.OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult; begin Result := S_OK; end; { TFileDownLoadThread } constructor TFileDownLoadThread.Create(ASrcURL, ASaveFileName: string; AProgressEvent: TDownLoadProcessEvent; ACompleteEvent: TDownLoadCompleteEvent; AFailEvent: TDownLoadFailEvent; CreateSuspended: Boolean); begin if (@AProgressEvent = nil) or (@ACompleteEvent = nil) or (@AFailEvent = nil) then CreateSuspended := True; inherited Create(CreateSuspended); FSourceURL := ASrcURL; FSaveFileName := ASaveFileName; FOnProcess := AProgressEvent; FOnComplete := ACompleteEvent; FOnFail := AFailEvent; end; procedure TFileDownLoadThread.DoUpdateUI; begin if Assigned(FOnProcess) then FOnProcess(Self, FProgress, FProgressMax); end; procedure TFileDownLoadThread.Execute; var DownRet: HRESULT; begin inherited; FMonitor := TDownLoadMonitor.Create(Self); DownRet := URLDownloadToFile(nil, PAnsiChar(FSourceURL), PAnsiChar(FSaveFileName), 0, FMonitor as IBindStatusCallback); if DownRet = S_OK then begin if Assigned(FOnComplete) then FOnComplete(Self); end else begin if Assigned(FOnFail) then FOnFail(Self, DownRet); end; FMonitor := nil; end; procedure TFileDownLoadThread.UpdateProgress(Progress, ProgressMax, StatusCode: Cardinal; StatusText: string); begin FProgress := Progress; FProgressMax := ProgressMax; Synchronize(DoUpdateUI); if Terminated then FMonitor.ShouldAbort := True; end; end. //使用unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, UrlMon, FileDownLoadThread; type TfrmDownloadFile = class(TForm) btn1: TButton; pb1: TProgressBar; lbl1: TLabel; lbl2: TLabel; procedure FormCreate(Sender: TObject); procedure btn1Click(Sender: TObject); private aRunThread: TFileDownLoadThread; public SourceFile, DestFile: string; procedure DownLoadProcessEvent(Sender: TFileDownLoadThread; Progress, ProgressMax: Cardinal); procedure DownLoadCompleteEvent(Sender: TFileDownLoadThread); procedure DownLoadFailEvent(Sender: TFileDownLoadThread; Reason: LongInt); end; var frmDownloadFile: TfrmDownloadFile; implementation {$R *.dfm} procedure TfrmDownloadFile.FormCreate(Sender: TObject); begin AppendMenu(GetSystemMenu(Handle, false), 0, 0, '程序: 花太香, QQ号: 2111971'); end; procedure TfrmDownloadFile.btn1Click(Sender: TObject); begin SourceFile := 'http://toolbar.soso.com/T4/download/QQToolbarInstaller.exe'; DestFile := '.QQToolbarInstaller.exe'; lbl1.Caption := '0/0'; lbl2.Caption := ''; pb1.Position := 0; lbl2.Caption := '正在下载:' + ExtractFileName(DestFile); aRunThread := TFileDownLoadThread.Create(SourceFile, DestFile, DownLoadProcessEvent, DownLoadCompleteEvent, DownLoadFailEvent, False); end; procedure TfrmDownloadFile.DownLoadProcessEvent( Sender: TFileDownLoadThread; Progress, ProgressMax: Cardinal); var z, z1: Single; s, s1: string; begin pb1.Position := Progress; pb1.Max := ProgressMax; if (pb1.Max > 0) then begin if pb1.Max > 1024 * 1024 then begin z := pb1.Max / (1024 * 1024); s := 'MB'; end else begin z := pb1.Max / (1024); s := 'KB'; end; if Progress > 1024 * 1024 then begin z1 := Progress / (1024 * 1024); s1 := 'MB'; end else begin z1 := Progress / (1024); s1 := 'KB'; end; lbl1.Caption := Format('%.2n' + s1 + ' / %.2n' + s, [z1, z]); end; end; procedure TfrmDownloadFile.DownLoadCompleteEvent( Sender: TFileDownLoadThread); begin lbl2.Caption := '下载完成.'; lbl1.Caption := ''; end; procedure TfrmDownloadFile.DownLoadFailEvent(Sender: TFileDownLoadThread; Reason: Integer); begin lbl2.Caption := '下载文件失败,请重试!'; end; end.