实用控件:将任意文件打包进dfm(zlib压缩)的控件 [转]

该控件可以将任意文件打包进.dfm(使用zlib压缩),可以用该控件编写只有一个exe的绿色软件,或者用于自己编写安装程序。
使用非常简单,设计期将该控件放入form, 指定FileName属性即可将该文件内容打包进dfm中。运行时可以调用FileRes1.ResToFile解压到指定的文件内或通过FileRes1.ResToStream解压到一个stream中(比如图片文件,接下去可以用Bitmap.LoadFromStream读入),这两个函数的Keep参数指定是否在操作的同时释放FileRes中占用的内存(如果只需要在程序运行时解压一次则建议使用Keep := False; 这样可以降低程序占用的内存)
unit FileRes;
interface
uses
  SysUtils, Classes, Windows, ZLib;
type
  TBufferStream = class(TStream)
  private
    FLen: Cardinal;
    FBuffer: Pointer;
    FPosition: Cardinal;
  protected
    procedure SetSize(NewSize: Longint); override;
  public
    destructor Destroy; override;
    function Read(var Buffer; Count: Longint): Longint; override;
    function Seek(Offset: Longint; Origin: Word): Longint; override;
    function Write(const Buffer; Count: Longint): Longint; override;
    procedure SaveToFile(FileName: string);
    procedure LoadFromFile(FileName: string);
    function SaveToStream(Stm: TStream): Integer;
    procedure LoadFromStream(Stm: TStream);
    function ReadString: string;
    procedure Writestring(const Str: string);
    procedure ExchangeBuffer(var ABuffer: Pointer; var ALen: Integer);
    property Buffer: Pointer read FBuffer;
  end;
  TFileRes = class(TComponent)
  private
    { Private declarations }
    FStream: TBufferStream;
    FFileName: TFileName;
    procedure WriteFileData(Stm: TStream);
    procedure ReadFileData(Stm: TStream);
    procedure SetFileName(const Value: TFileName);
  protected
    { Protected declarations }
    procedure DefineProperties(Filer: TFiler); override;
  public
    { Public declarations }
    destructor Destroy; override;
    function ResToFile(AFileName: string; Keep: Boolean = false): Boolean;
    function ResToStream(var Stm: TStream; Keep: Boolean = false): Boolean;
    property Stream: TBufferStream read FStream;
  published
    { Published declarations }
    property FileName: TFileName read FFileName write SetFileName;
  end;
procedure Register;
implementation
procedure Register;
begin
  RegisterComponents('Standard', [TFileRes]);
end;
{ TBufferStream }
destructor TBufferStream.Destroy;
begin
  reallocmem(fbuffer, 0);
  inherited;
end;
procedure TBufferStream.ExchangeBuffer(var ABuffer: Pointer;
  var ALen: Integer);
var
  tmp: Integer;
begin
  tmp := Integer(ABuffer);
  ABuffer := FBuffer;
  FBuffer := Pointer(tmp);
  tmp := ALen;
  ALen := FLen;
  FLen := tmp;
  if FPosition > FLen then FPosition := FLen;
end;
procedure TBufferStream.LoadFromFile(FileName: string);
var
  fid: Integer;
begin
  reallocmem(fbuffer, 0);
  flen := 0;
  fid := fileopen(filename, fmOpenRead or fmShareDenyNone);
  if fid < 0 then exit;
  flen := getfilesize(fid, nil);
  reallocmem(fbuffer, flen);
  fileread(fid, fbuffer^, flen);
  fileclose(fid);
  position := 0;
end;
procedure TBufferStream.LoadFromStream(Stm: TStream);
var
  buf: Pointer;
  l: Integer;
begin
  reallocmem(fbuffer, 0);
  flen := 0;
  fposition := 0;
  stm.Read(l, 4);
  if l > 0 then
  begin
    getmem(buf, l);
    stm.Read(buf^, l);
    try
      decompressbuf(buf, l, l, fbuffer, Integer(flen));
    except
      fbuffer := nil;
    end;
    freemem(buf);
  end;
end;
function TBufferStream.Read(var Buffer; Count: Integer): Longint;
begin
  if fposition+count>flen then result := flen-fposition
  else result := count;
  if result > 0 then
  begin
    move(PByteArray(fbuffer)[fposition], buffer, result);
    inc(fposition, result);
  end;
end;
function TBufferStream.ReadString: string;
var
  l: Integer;
begin
  read(l, 4);
  setlength(result, l);
  if l > 0 then
    read(result[1], l);
end;
procedure TBufferStream.SaveToFile(FileName: string);
var
  fid: Integer;
begin
  fid := filecreate(filename);
  if fid < 0 then exit;
  if flen > 0 then
    filewrite(fid, fbuffer^, flen);
  fileclose(fid);
end;
function TBufferStream.SaveToStream(Stm: TStream): Integer;
var
  buf: Pointer;
begin
  try
    compressbuf(fbuffer, flen, buf, result);
  except
    result := 0;
  end;
  stm.Write(result, 4);
  if result > 0 then
  begin
    stm.Write(buf^, result);
    freemem(buf);
  end;
  inc(result, 4);
end;
function TBufferStream.Seek(Offset: Integer; Origin: Word): Longint;
begin
  case origin of
    0: if offset >= 0 then fposition := offset;
    1: inc(fposition, offset);
    2: fposition := flen + offset;
  end;
  result := fposition;
end;
procedure TBufferStream.SetSize(NewSize: Integer);
begin
  if flen <> newsize then
  begin
    flen := newsize;
    reallocmem(fbuffer, newsize);
    if fposition > flen then fposition := flen;
  end;
end;
function TBufferStream.Write(const Buffer; Count: Integer): Longint;
begin
  try
    if fposition + count > flen then
      setsize(fposition + count);
    result := count;
    move(buffer, PByteArray(fbuffer)[fposition], count);
    inc(fposition, count);
  except
    result := 0;
  end;
end;
procedure TBufferStream.Writestring(const Str: string);
var
  l: Integer;
begin
  l := Length(str);
  write(l, 4);
  if l > 0 then
    write(str[1], l);
end;
{ TFileRes }
destructor TFileRes.Destroy;
begin
  if assigned(FStream) then
    fstream.Free;
  inherited;
end;
procedure TFileRes.DefineProperties(Filer: TFiler);
begin
  inherited;
  filer.DefineBinaryProperty('FileStreamData', ReadFileData, WriteFileData, assigned(fstream));
end;
procedure TFileRes.ReadFileData(Stm: TStream);
begin
  if not assigned(fstream) then
    fstream := TBufferStream.Create;
  fstream.LoadFromStream(stm);
end;
procedure TFileRes.WriteFileData(Stm: TStream);
begin
  if assigned(fstream) then
    fstream.SaveToStream(stm);
end;
function TFileRes.ResToFile(AFileName: string; Keep: Boolean): Boolean;
var
  fid: Integer;
begin
  result := false;
  if not assigned(fstream) then exit;
  fid := filecreate(afilename);
  if fid < 0 then exit;
  if fstream.FLen > 0 then
    filewrite(fid, fstream.fbuffer^, fstream.FLen);
  fileclose(fid);
  result := true;
  if not keep then
    freeandnil(fstream);
end;
function TFileRes.ResToStream(var Stm: TStream; Keep: Boolean): Boolean;
begin
  result := assigned(fstream);
  if result then
  begin
    stm := fstream;
    if not keep then
      fstream := nil;
  end;
end;
procedure TFileRes.SetFileName(const Value: TFileName);
begin
  if (csDesigning in ComponentState) {and (value <> ffilename)} then
  begin
    FFileName := Value;
    if not (csLoading in ComponentState) then
      if value <> '' then
      begin
        if not assigned(fstream) then
          fstream := TBufferStream.Create;
        fstream.LoadFromFile(value);
        if fstream.FLen = 0 then
          freeandnil(fstream);
      end
      else freeandnil(fstream);
  end;
end;
end. 

posted @ 2011-10-09 15:25  翔飞  阅读(251)  评论(0编辑  收藏  举报