UrlDownloadFile, 线程下载文件, 带进度条

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 = nilor (@ACompleteEvent = nilor (@AFailEvent = nilthen 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), 
00'程序: 花太香, 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 > 0then
  
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. 

原文地址:https://www.cnblogs.com/jxgxy/p/2043703.html