home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 March / Chip_1998-03_cd.bin / zkuste / delphi / komprese / zip / DELZIP12.ZIP / DEMO3.ZIP / UNIT1.PAS < prev    next >
Pascal/Delphi Source File  |  1997-09-28  |  25KB  |  795 lines

  1. { unit1.pas   a demo of freeware ZIP/UNZIP DLLs for Delphi v2
  2.   This is the main unit of the advanced Zip/Unzip Demo projoect, zipdemo3.
  3.   Both of these DLLs are required to run this program: ZIPDLL.DLL, UNZDLL.DLL.
  4.   Also, both of these VCL's must be installed before opening this
  5.   project in Delphi: ZipDir and SortGrid.
  6.   See README.TXT for more info. }
  7.  
  8. unit Unit1;
  9.  
  10. interface
  11.  
  12. uses
  13.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  14.   ZIPDLL, UNZDLL, ZCallBck, StdCtrls, ExtCtrls, TZipList, Extrunit, ComCtrls;
  15.  
  16. type
  17.   TForm1 = class(TForm)
  18.     Panel1: TPanel;
  19.     RadioTraceOpt: TRadioGroup;
  20.     Panel2: TPanel;
  21.     RadioVerboseOpt: TRadioGroup;
  22.     Label1: TLabel;
  23.     Label2: TLabel;
  24.     Label3: TLabel;
  25.     Edit1: TEdit;
  26.     Edit2: TEdit;
  27.     RadioRecurse: TRadioGroup;
  28.     Panel3: TPanel;
  29.     Panel4: TPanel;
  30.     ProgressBar1: TProgressBar;
  31.     FileBeingZipped: TLabel;
  32.     Memo1: TMemo;
  33.     NewBut: TButton;
  34.     OpenBut: TButton;
  35.     ZipFName: TLabel;
  36.     OpenDialog: TOpenDialog;
  37.     VersionBut: TButton;
  38.     ListBut: TButton;
  39.     AddBut: TButton;
  40.     DeleteBut: TButton;
  41.     ExtractBut: TButton;
  42.     AbortBut: TButton;
  43.     ExitBut: TButton;
  44.     procedure FormCreate(Sender: TObject);
  45.     procedure VersionButClick(Sender: TObject);
  46.     procedure ExitButClick(Sender: TObject);
  47.     procedure ListButClick(Sender: TObject);
  48.     procedure AddButClick(Sender: TObject);
  49.     procedure DeleteButClick(Sender: TObject);
  50.     procedure AbortButClick(Sender: TObject);
  51.     procedure SetZipSwitches(Opt: ZipOpt);
  52.     procedure SetUnZipSwitches;
  53.     procedure AddToMemo(s: String);
  54.     procedure ResetProgressBar;
  55.     procedure ExtractButClick(Sender: TObject);
  56.     procedure OpenButClick(Sender: TObject);
  57.     procedure NewButClick(Sender: TObject);
  58.     procedure FormDestroy(Sender: TObject);
  59.   private
  60.     { Private declarations }
  61.     ZipParms1: ZipParms;     { declare an instance of ZipParms }
  62.     UnZipParms1: UnZipParms; { declare an instance of UnZipParms }
  63.     procedure SetNewZipFile(FName: String; NewFile: Boolean);
  64.     procedure Load_Zip_Dll;
  65.     procedure Load_Unz_Dll;
  66.     procedure Unload_Zip_Dll;
  67.     procedure Unload_Unz_Dll;
  68.   public
  69.     { Public declarations }
  70.     ExtractDir: String;
  71.     ExpandDirs: Boolean;
  72.     Overwrite: Boolean;
  73. end;
  74.  
  75. var
  76.   Form1: TForm1;
  77.   AbortRequested: Boolean;
  78.   { The callback function must NOT be a member of a class }
  79.   { I'm going to use the same callback function for ZIP and UNZIP }
  80.   function ZCallback(ZCallBackRec: PZCallBackStruct): LongBool; stdcall; export;
  81.  
  82. implementation
  83.  
  84. {$R *.DFM}
  85.  
  86. { Notes on the types of callbacks we'll get form the DLL.
  87.    This provides the calling program with updated info on what the DLL
  88.    is doing.  Regardless of the type of call being made, the user's
  89.    function must end with a spin of the message loop.  In fact, even
  90.    if user isn't using a progress bar, then he should still spin the msg
  91.    loop upon getting these callbacks (but he doesn't need to do anything
  92.    else).  Here are the types of call backs:
  93.  
  94.      ActionCode = 1, we're starting a zip operation on a new file
  95.         ErrorCode = not used yet
  96.         fsize = filesize of file we're going to operate on
  97.         name = pathname of file
  98.      IMPORTANT: The user's function must do the math for the progress
  99.      bar upon getting this call.
  100.  
  101.      ActionCode = 2, increment the progress bar
  102.         These calls will occur after every 32K of input file has been
  103.         processed. One additional call is made at the end of each file,
  104.         just to make sure the progress bar is max'ed out - this is also
  105.         critical for files less than 32K in size (this last one will be
  106.         their only one).
  107.         ErrorCode = N/A
  108.         fsize = N/A
  109.         name = N/A
  110.  
  111.      ActionCode = 3, we're done with a batch of files - program flow
  112.      will quickly return to the user's program.
  113.      NOTE: the end of a every file will always be followed by an
  114.            action of 1 or 3, so a separate call for end of one file
  115.            isn't needed.
  116.         ErrorCode = N/A
  117.         fsize = N/A
  118.         name = N/A
  119.  
  120.      ActionCode = 4, a routine status message has been issued by the DLL.
  121.      It is in the NameOrMsg field.
  122. }
  123. function ZCallback(ZCallBackRec: PZCallBackStruct): LongBool; stdcall; export;
  124. var
  125.    FSize: LongInt;
  126. begin
  127.    with ZCallBackRec^, (TObject(Caller) as TForm1) do
  128.    begin
  129.       if ActionCode = 1 then
  130.       begin
  131.          { starting any ZIP operation on a new file }
  132.          FileBeingZipped.Caption:=StrPas(FileNameOrMsg);
  133.          FSize:=FileSize;
  134.          with ProgressBar1 do
  135.          begin
  136.             if (not visible) then
  137.                visible:=true;
  138.             { Max is assigned the approximate # of callbacks }
  139.             if (FSize div 32768) > 1 then
  140.                Max := FSize div 32768  { total no of steps }
  141.             else
  142.                Max := 1;
  143.             Min:=1;      { first step }
  144.             Step := 1;   { no. of steps for each "StepIt" }
  145.             Position:=1; { current position of bar }
  146.             if (FSize < 32768) then
  147.                StepIt;   { max out progress for small files }
  148.          end;
  149.       end;
  150.  
  151.       { increment the progress bar }
  152.       if (ActionCode = 2) then
  153.       begin
  154.          with ProgressBar1 do
  155.          begin
  156.            { By making sure that you're not already at maximum, you
  157.              can avoid problems in case the callback signaling the
  158.              end is redundant with the last increment message }
  159.            { if given too many steps, the progress bar wraps around }
  160.            if Position < Max then
  161.               StepIt;
  162.          end;
  163.       end;
  164.  
  165.       { end of a batch of 1 or more files }
  166.       if (ActionCode = 3) Then
  167.       begin
  168.          ResetProgressBar;
  169.       end;
  170.  
  171.       { show a routine status message }
  172.       if (ActionCode = 4) Then
  173.       begin
  174.          AddToMemo(StrPas(FileNameOrMsg));
  175.          if not (ErrorCode = 0) then
  176.             { We got a serious error - give user a dialog box }
  177.             ShowMessage('ERROR: ' + FileNameOrMsg
  178.                  + '   code=' + IntToStr(ErrorCode));
  179.       end;
  180.    end; { end with }
  181.  
  182.    { This call is mandatory here (even if no progress bar is used): }
  183.    Application.ProcessMessages;
  184.  
  185.    { If you return TRUE, then the DLL will abort it's current
  186.      batch job as soon as it can. }
  187.    if AbortRequested then
  188.       result:=True
  189.    else
  190.       result:=False;
  191. end;
  192.  
  193. {----------------------------------------------------------------}
  194.  
  195. procedure TForm1.AddToMemo(s: String);
  196. var
  197.    EndPos: Integer;
  198. begin
  199.    { Remove possible trailing CR or LF }
  200.    EndPos:=Length(s);
  201.    if ((s[EndPos] = #13)
  202.     or (s[EndPos] = #10)) then
  203.        s[EndPos] := #0;
  204.    if EndPos > 1 then
  205.    begin
  206.       if ((s[EndPos-1] = #13)
  207.        or (s[EndPos-1] = #10)) then
  208.           s[EndPos-1] := #0;
  209.    end;
  210.    Memo1.Lines.Add(s);
  211. end;
  212.  
  213. procedure TForm1.ResetProgressBar;
  214. begin
  215.    FileBeingZipped.Caption:='';
  216.    with ProgressBar1 do
  217.    begin   { reset the bar: make it empty }
  218.       min:=1;
  219.       max:=10;
  220.       step:=1;
  221.       position:=min;
  222.    end;
  223. end;
  224.  
  225. procedure TForm1.FormCreate(Sender: TObject);
  226. begin
  227.    RadioTraceOpt.ItemIndex:=0;  { default to no tracing }
  228.    RadioVerboseOpt.ItemIndex:=1;{ default to show verbose msgs }
  229.    RadioRecurse.ItemIndex:=0;   { dflt to no recursive adds of files }
  230.    AbortRequested:=False;
  231.    AbortBut.Enabled:=False;
  232.    ResetProgressBar;
  233.    { IMPORTANT!  Either make sure you're in the same dir as all your
  234.      files, or else use full pathnames on all your files. }
  235.    Caption:='ZIP Demo - ' + GetCurrentDir;
  236.    Load_Zip_Dll;
  237.    Load_Unz_Dll;
  238. end;
  239.  
  240. procedure TForm1.VersionButClick(Sender: TObject);
  241. var
  242.    ZipVers, UnzVers: Integer;
  243.    ZipGood, UnzGood: Boolean;
  244. begin
  245.    ZipVers:=0;
  246.    UnzVers:=0;
  247.    try
  248.       ZipVers:=GetZipDLLVersion;
  249.       ZipGood:=True;  { no exception - the call worked }
  250.    except
  251.       ShowMessage('Error talking to ZIPDLL.DLL');
  252.       ZipGood:=False;
  253.    end;
  254.  
  255.    try
  256.       { notice the trailing U on function name below }
  257.       UnzVers:=GetUnzDLLVersion;
  258.       UnzGood:=True;  { no exception - the call worked }
  259.    except
  260.       ShowMessage('Error talking to UNZDLL.DLL');
  261.       UnzGood:=False;
  262.    end;
  263.  
  264.    if ZipGood and UnzGood then
  265.       ShowMessage('ZIPDLL.DLL version is '
  266.        + IntToStr(ZipVers) + #13#10#13#10
  267.        + 'UNZDLL.DLL version is '
  268.        + IntToStr(UnzVers));
  269. end;
  270.  
  271. procedure TForm1.ExitButClick(Sender: TObject);
  272. begin
  273.    Close;
  274. end;
  275.  
  276. procedure TForm1.ListButClick(Sender: TObject);
  277. begin
  278.    { I'm making this modal bec. I don't want the zipfile to be
  279.      changed while it's contents are being viewed. }
  280.    if not FileExists(ZipFName.Caption) then
  281.    begin
  282.       ShowMessage('Error: file not found: ' + ZipFName.Caption);
  283.       exit;
  284.    end;
  285.    VersionBut.Enabled:=False;
  286.    DeleteBut.Enabled:=False;
  287.    AddBut.Enabled:=False;
  288.    ExitBut.Enabled:=False;
  289.    ListBut.Enabled:=False;
  290.    ExtractBut.Enabled:=False;
  291.  
  292.    ZipForm.ShowModal;  { we're using a separate form for the List function }
  293.  
  294.    VersionBut.Enabled:=True;
  295.    DeleteBut.Enabled:=True;
  296.    AddBut.Enabled:=True;
  297.    ExitBut.Enabled:=True;
  298.    ListBut.Enabled:=True;
  299.    ExtractBut.Enabled:=True;
  300. end;
  301.  
  302. procedure TForm1.AddButClick(Sender: TObject);
  303. var
  304.    i, return_code: Integer;
  305. begin
  306.    if ((Length(ZipFName.Caption) = 0) or (Length(Edit1.Text) = 0)) then
  307.    begin
  308.       ShowMessage('Error: you need at least name of zip, and 1st filespec to add');
  309.       exit;
  310.    end;
  311.    VersionBut.Enabled:=False;
  312.    DeleteBut.Enabled:=False;
  313.    AddBut.Enabled:=False;
  314.    ExitBut.Enabled:=False;
  315.    ListBut.Enabled:=False;
  316.    ExtractBut.Enabled:=False;
  317.  
  318.    SetZipSwitches(ZipAdd);
  319.  
  320.    with ZipParms1 do
  321.    begin
  322.       PZipFN := StrAlloc(256);  { allocate room for null terminated string }
  323.       StrPCopy(PZipFN, ZipFName.Caption);   { name of zip file }
  324.       argc:=0;  { init to zero }
  325.  
  326.       if Length(Edit1.Text) > 0 then
  327.       begin
  328.          PFileNames[argc]:=StrAlloc(256);  { alloc room for the filespec }
  329.          StrPCopy(PFileNames[argc], Edit1.Text);  { first file to add to archive }
  330.          argc:=argc+1;
  331.       end;
  332.  
  333.       if Length(Edit2.Text) > 0 then
  334.       begin
  335.          PFileNames[argc]:=StrAlloc(256);
  336.          StrPCopy(PFileNames[argc], Edit2.Text);
  337.          argc:=argc+1;
  338.       end;
  339.       { argc is now the no. of filespecs we want added/deleted }
  340.    end;  { end with }
  341.    return_code:=0;
  342.    Cursor:=crHourGlass;
  343.    AbortBut.Enabled:=True;
  344.    try
  345.      return_code:=ZipDllExec(@ZipParms1);  { pass in a ptr to parms }
  346.    finally
  347.      Cursor:=crDefault;
  348.      if (return_code < 0) then
  349.         ShowMessage('Fatal error in DLL');
  350.      ShowMessage('DONE: Number of files zipped up: ' + IntToStr(return_code));
  351.      with ZipParms1 do
  352.      begin
  353.         StrDispose(PZipFN);
  354.         for i := 0 to argc - 1 do
  355.            StrDispose(PFileNames[i]);
  356.      end;
  357.    end;
  358.  
  359.    if AbortRequested then
  360.    begin
  361.       { The "add" was aborted by the user. }
  362.       AbortRequested:=False;
  363.       { IMPORTANT!  If an "add" is aborted, it is possible that
  364.         the ZIP file is now corrupted.  If you especially concerned
  365.         about this, make a backup copy of the ZIP file before an "add"
  366.         operation , and if you detect that the "add" was aborted, then
  367.         copy your backup over the top of the current ZIP file.
  368.         The "delete" is non-abortable, since it executes quickly.}
  369.    end;
  370.    ResetProgressBar;
  371.    VersionBut.Enabled:=True;
  372.    DeleteBut.Enabled:=True;
  373.    AddBut.Enabled:=True;
  374.    ExitBut.Enabled:=True;
  375.    ListBut.Enabled:=True;
  376.    AbortBut.Enabled:=False;
  377.    ExtractBut.Enabled:=True;
  378. end;
  379.  
  380. procedure TForm1.DeleteButClick(Sender: TObject);
  381. var
  382.    i, return_code: Integer;
  383. begin
  384.    VersionBut.Enabled:=False;
  385.    DeleteBut.Enabled:=False;
  386.    AddBut.Enabled:=False;
  387.    ExitBut.Enabled:=False;
  388.    ListBut.Enabled:=False;
  389.    ExtractBut.Enabled:=False;
  390.  
  391.    if ((Length(ZipFName.Caption) = 0) or (Length(Edit1.Text) = 0)) then
  392.    begin
  393.       ShowMessage('Error: you need at least name of zip, and 1st filespec to add');
  394.       exit;
  395.    end;
  396.    if not FileExists(ZipFName.Caption) then
  397.    begin
  398.       ShowMessage('Error: file not found: ' + ZipFName.Caption);
  399.       exit;
  400.    end;
  401.  
  402.    SetZipSwitches(ZipDelete);
  403.  
  404.    with ZipParms1 do
  405.    begin
  406.       PZipFN := StrAlloc(256);  { allocate room for null terminated string }
  407.       StrPCopy(PZipFN, ZipFName.Caption);   { name of zip file }
  408.       argc:=0;  { init to zero }
  409.  
  410.       if Length(Edit1.Text) > 0 then
  411.       begin
  412.          PFileNames[argc]:=StrAlloc(256);  { alloc room for the filespec }
  413.          StrPCopy(PFileNames[argc], Edit1.Text);  { first file to add to archive }
  414.          argc:=argc+1;
  415.       end;
  416.  
  417.       if Length(Edit2.Text) > 0 then
  418.       begin
  419.          PFileNames[argc]:=StrAlloc(256);
  420.          StrPCopy(PFileNames[argc], Edit2.Text);
  421.          argc:=argc+1;
  422.       end;
  423.       { argc is now the no. of filespecs we want added/deleted }
  424.    end;  { end with }
  425.  
  426.    return_code:=0;
  427.    Cursor:=crHourGlass;
  428.    AbortBut.Enabled:=False;  { The DELETE option doesn't support abort }
  429.    try
  430.      return_code:=ZipDllExec(@ZipParms1);  { pass in a ptr to parms }
  431.    finally
  432.      Cursor:=crDefault;
  433.      if (return_code < 0) then
  434.         ShowMessage('Fatal error in DLL');
  435.      ShowMessage('DONE: Number of files deleted: ' + IntToStr(return_code));
  436.      with ZipParms1 do
  437.      begin
  438.         StrDispose(PZipFN);
  439.         for i := 0 to argc - 1 do
  440.            StrDispose(PFileNames[i]);
  441.      end;
  442.    end;
  443.    AbortRequested:=False;
  444.    ResetProgressBar;
  445.    VersionBut.Enabled:=True;
  446.    DeleteBut.Enabled:=True;
  447.    AddBut.Enabled:=True;
  448.    ExitBut.Enabled:=True;
  449.    ListBut.Enabled:=True;
  450.    AbortBut.Enabled:=False;
  451.    ExtractBut.Enabled:=True;
  452. end;
  453.  
  454. procedure TForm1.SetZipSwitches(Opt: ZipOpt);
  455. begin
  456.    Memo1.Lines.Clear;
  457.    with ZipParms1 do
  458.    begin
  459.       Version:=120;    // version we expect the DLL to be
  460.       Caller := Self;  // point to our Form instance
  461.       ZipParms1.Handle:=Form1.Handle; // pass window handle
  462.       ZCallbackFunc:=ZCallback; // pass addr of function to be called from DLL
  463.  
  464.       if RadioTraceOpt.ItemIndex = 0 then
  465.          fTraceEnabled:=false
  466.       else
  467.          fTraceEnabled:=true;
  468.       if RadioVerboseOpt.ItemIndex = 0 then
  469.          fVerboseEnabled:=false
  470.       else
  471.          fVerboseEnabled:=true;
  472.       if ((RadioRecurse.ItemIndex = 1) and (Opt = ZipAdd)) then
  473.          fRecurse:=true
  474.       else
  475.          fRecurse:=false;
  476.  
  477.       fEncryptVerify:=false; { not supported }
  478.       fEncrypt:=false;       { not supported }
  479.  
  480.       fQuiet:=true;  { we report errors upon notification in our callback }
  481.  
  482.       fNoDirEntries:=False; { save dir names as separate entries? }
  483.       fJunkDir:=False;      { if true, junk directory names }
  484.  
  485.       fJunkSFX:=false;      { if true, convert input .EXE file to .ZIP }
  486.       fLatestTime:=false;   { if true, make zipfile's timestamp same as newest file }
  487.       fComprSpecial:=false; { if true, try to compr already compressed files }
  488.       fSystem:=false;    { if true, include system and hidden files }
  489.       fVolume:=false;    { if true, include volume label from root dir }
  490.       fExtra:=false;     { if true, include extended file attributes }
  491.       fDate:=false;      { if true, exclude files earlier than specified date }
  492.       { Date:= '100592'; } { Date to include files after; only used if fDate=TRUE }
  493.  
  494.       fLevel:=9;        { Compression level (0 - 9, 0=none and 9=best) }
  495.       fCRLF_LF:=false;  { if true, translate text file CRLF to LF (if dest is Unix) }
  496.  
  497.       fForce:=false;    { if true, convert all filenames to 8x3 format }
  498.       fMove:=false;     { if true, Delete orig files that were added or updated }
  499.       { if opt=add (dflt), and update and freshen are both false,
  500.         you get unconditional add/overwrite }
  501.       fUpdate:=false;   { if true, rezip changed, and add new files in fspec }
  502.       fFreshen:=false;  { if true, rezip all changed files in fspec }
  503.  
  504.       fDeleteEntries:=false;  { override later, if needed. }
  505.  
  506.       { Grow has to be true to create a new ZIP file }
  507.       fGrow:=false;     { if true, Allow appending to a zip file  (-g)}
  508.  
  509.       { NOTE: Freshen, Update, and Move are only variations of Add }
  510.       { The LIST function is being handled by the TZReader Delphi VCL }
  511.       case Opt of
  512.          ZipAdd:    fGrow := True;  { if true, Allow appending to a zip file (-g)}
  513.          ZipDelete: fDeleteEntries := True; { allow deletions from ZIPFILE }
  514.       end; { end case }
  515.       seven:=7;
  516.    end; { end with }
  517. end;
  518.  
  519. procedure TForm1.SetUnZipSwitches;
  520. begin
  521.    Memo1.Lines.Clear;
  522.    with UnZipParms1 do
  523.    begin
  524.       Version:=120;    // version we expect the DLL to be
  525.       Caller := Self;  // set our form instance
  526.       ZipParms1.Handle:=Form1.Handle; // pass window handle
  527.       ZCallbackFunc:=ZCallback; // pass addr of function to be called from DLL
  528.  
  529.       if RadioTraceOpt.ItemIndex = 0 then
  530.          fTraceEnabled:=false
  531.       else
  532.          fTraceEnabled:=true;
  533.       if RadioVerboseOpt.ItemIndex = 0 then
  534.          fVerboseEnabled:=false
  535.       else
  536.          fVerboseEnabled:=true;
  537.  
  538.       fQuiet:=true;   { we report errors upon notification in our callback }
  539.       fOverwrite:=Overwrite;    { if true, overwrite existing files }
  540.       fDirectories:=ExpandDirs; { if ture, recreate zip dir structure }
  541.       fUpdate:=false;   { if true, unzip if file in ZIP has a newer date/time, or is totally new }
  542.       fFreshen:=false;  { if true, unzip if file in ZIP has a newer date/time }
  543.  
  544.       fDecrypt:=false;  { decryption - not supported }
  545.       fComments:=false; { zipfile comments - not supported }
  546.       fConvert:=false;  { ascii/EBCDIC conversion - not supported }
  547.       fTest:=false;     { test zipfile - not supported }
  548.       seven:=7;
  549.    end; { end with }
  550. end;
  551.  
  552. procedure TForm1.AbortButClick(Sender: TObject);
  553. begin
  554.    { This will be passed back to the DLL upon finishing processing
  555.      of the next callback }
  556.    AbortRequested:=True;
  557.    AbortBut.Enabled:=False;
  558. end;
  559.  
  560. procedure TForm1.ExtractButClick(Sender: TObject);
  561. var
  562.    i, return_code: Integer;
  563.    SaveDir: String;
  564. begin
  565.    if (Length(ZipFName.Caption) = 0) then
  566.    begin
  567.       ShowMessage('Error: you need name of zipfile');
  568.       exit;
  569.    end;
  570.    ExtractDir:='';
  571.    SaveDir:=GetCurrentDir;
  572.    { let user select extract directory,
  573.      whether to expand the zip file's dir's,
  574.      and whether to overwrite existing files }
  575.    Extract.ShowModal;
  576.    if Length(ExtractDir) = 0 then
  577.       exit;
  578.  
  579.    SetCurrentDir(ExtractDir);
  580.    if (GetCurrentDir <> ExtractDir) then
  581.    begin
  582.       ShowMessage('Error selecting dir: ' + ExtractDir);
  583.       Exit;
  584.    end;
  585.  
  586.    VersionBut.Enabled:=False;
  587.    DeleteBut.Enabled:=False;
  588.    AddBut.Enabled:=False;
  589.    ExitBut.Enabled:=False;
  590.    ListBut.Enabled:=False;
  591.    ExtractBut.Enabled:=False;
  592.  
  593.    SetUnZipSwitches;
  594.  
  595.    with UnZipParms1 do
  596.    begin
  597.       PZipFN := StrAlloc(256);  { allocate room for null terminated string }
  598.       StrPCopy(PZipFN, ZipFName.Caption);   { name of zip file }
  599.       argc:=0;  { init to zero }
  600.  
  601.       if Length(Edit1.Text) > 0 then
  602.       begin
  603.          PFileNames[argc]:=StrAlloc(256);  { alloc room for the filespec }
  604.          StrPCopy(PFileNames[argc], Edit1.Text);  { first file to add to archive }
  605.          argc:=argc+1;
  606.       end;
  607.  
  608.       if Length(Edit2.Text) > 0 then
  609.       begin
  610.          PFileNames[argc]:=StrAlloc(256);
  611.          StrPCopy(PFileNames[argc], Edit2.Text);
  612.          argc:=argc+1;
  613.       end;
  614.       { argc is now the no. of filespecs we want added/deleted }
  615.    end;  { end with }
  616.  
  617.    Cursor:=crHourGlass;
  618.    AbortBut.Enabled:=True;
  619.    Memo1.Lines.Add('Unzip base directory: ' + ExtractDir);
  620.    return_code:=0;
  621.    try
  622.      return_code:=UnzDllExec(@UnZipParms1);  { pass in a ptr to parms }
  623.    finally
  624.      Cursor:=crDefault;
  625.      ShowMessage('DONE: Number of files Unzipped: ' + IntToStr(return_code));
  626.      with UnZipParms1 do
  627.      begin
  628.         StrDispose(PZipFN);
  629.         for i := 0 to argc - 1 do
  630.            StrDispose(PFileNames[i]);
  631.      end;
  632.    end;
  633.  
  634.    if AbortRequested then
  635.    begin
  636.       AbortRequested:=False;
  637.       { IMPORTANT!  If a ZIP "Extract" is aborted, it is possible that
  638.         the file just expanded is now corrupted. Perhaps we should delete it?}
  639.    end;
  640.    VersionBut.Enabled:=True;
  641.    DeleteBut.Enabled:=True;
  642.    AddBut.Enabled:=True;
  643.    ExitBut.Enabled:=True;
  644.    ListBut.Enabled:=True;
  645.    AbortBut.Enabled:=False;
  646.    ExtractBut.Enabled:=True;
  647.  
  648.    SetCurrentDir(SaveDir);
  649.    if (GetCurrentDir <> SaveDir) then
  650.       ShowMessage('Error re-selecting dir: ' + SaveDir);
  651. end;
  652.  
  653. procedure TForm1.OpenButClick(Sender: TObject);
  654. begin
  655.    with OpenDialog do
  656.    begin
  657.       Title:='Open Existing ZIP File';
  658.       Options:=Options+[ofHideReadOnly,ofShareAware,ofPathMustExist,ofFileMustExist];
  659.       Filter :='ZIP Files (*.ZIP)|*.zip';
  660.       if Execute then
  661.          SetNewZipFile(Filename, False);
  662.    end;
  663. end;
  664.  
  665. procedure TForm1.SetNewZipFile(FName: String; NewFile: Boolean);
  666. var
  667.    Ans: Boolean;
  668.    i: Integer;
  669.    Extension: String;
  670. begin
  671.    { get the extension of the filename }
  672.    for i:=Length(FName)-1 downto 0 do
  673.       if FName[i] = '.' then
  674.       begin
  675.          Extension:=Copy(FName, i, Length(FName) - i + 1);
  676.          break;
  677.       end;
  678.    { if the extension isn't ZIP, then append a .zip extension onto it }
  679.    if (CompareText(Extension,'.zip') <> 0) then
  680.       FName:=FName+'.zip';
  681.  
  682.    { see if user wants a new zipfile, and if it already exists }
  683.    if NewFile and FileExists(FName) then
  684.    begin
  685.       Ans:=MessageDlg('Overwrite Existing File: ' + FName + '?',
  686.                           mtConfirmation,[mbYes,mbNo],0)=mrYes;
  687.       if Ans then
  688.          DeleteFile(FName)
  689.       else
  690.          Exit;  { Don't use the new name }
  691.    end;
  692.  
  693.    ZipFName.Caption:=FName;
  694.    { Change to the new drive/directory, so all filespecs will
  695.      be relative to the directory of the ZIP file. This is
  696.      very important for most ZIP application programs!  A
  697.      failure to do this will cause files and directories to
  698.      become all mixed up. }
  699.    SetCurrentDir(ExtractFileDir(FName));
  700.    Caption:='ZIP Demo1 - ' + GetCurrentDir;
  701.  
  702.    VersionBut.Enabled:=True;
  703.    DeleteBut.Enabled:=True;
  704.    AddBut.Enabled:=True;
  705.    ExitBut.Enabled:=True;
  706.    ListBut.Enabled:=True;
  707.    AbortBut.Enabled:=False;
  708.    ExtractBut.Enabled:=True;
  709.    Memo1.Lines.Clear;
  710. end;
  711.  
  712. procedure TForm1.NewButClick(Sender: TObject);
  713. begin
  714.    with OpenDialog do
  715.    begin
  716.       Title:='Create New ZIP File';
  717.       Options:=Options+[ofHideReadOnly,ofShareAware];
  718.       Options:=Options-[ofPathMustExist,ofFileMustExist];
  719.       Filter :='ZIP Files (*.ZIP)|*.zip';
  720.       if Execute then
  721.          SetNewZipFile(Filename, True);
  722.    end; { end with }
  723. end;
  724.  
  725. procedure TForm1.FormDestroy(Sender: TObject);
  726. begin
  727.    Unload_Zip_Dll;
  728.    Unload_Unz_Dll;
  729. end;
  730.  
  731. procedure TForm1.Load_Zip_Dll;
  732. begin
  733.    SetErrorMode(SEM_FAILCRITICALERRORS or SEM_NOGPFAULTERRORBOX);
  734.    try
  735.       ZipDllHandle := LoadLibrary('ZIPDLL.DLL');
  736.       if ZipDllHandle > HInstance_Error then
  737.       begin
  738.          @ZipDllExec := GetProcAddress(ZipDllHandle,'ZipDllExec');
  739.          @GetZipDllVersion := GetProcAddress(ZipDllHandle,'GetZipDllVersion');
  740.          if @ZipDllExec = nil then
  741.             ShowMessage('ZipDllExec function not found in ZIPDLL.DLL');
  742.          if @GetZipDllVersion = nil then
  743.             ShowMessage('GetZipDllVersion function not found in ZIPDLL.DLL');
  744.       end
  745.       else
  746.       begin
  747.          ZipDllHandle := 0; {reset}
  748.          ShowMessage('ZIPDLL.DLL not found');
  749.       end;
  750.    finally
  751.       SetErrorMode(0);
  752.    end;
  753. end;
  754.  
  755. procedure TForm1.Load_Unz_Dll;
  756. begin
  757.    SetErrorMode(SEM_FAILCRITICALERRORS or SEM_NOGPFAULTERRORBOX);
  758.    try
  759.       UnzDllHandle := LoadLibrary('UNZDLL.DLL');
  760.       if UnzDllHandle > HInstance_Error then
  761.       begin
  762.          @UnzDllExec := GetProcAddress(UnzDllHandle,'UnzDllExec');
  763.          @GetUnzDllVersion := GetProcAddress(UnzDllHandle,'GetUnzDllVersion');
  764.          if @UnzDllExec = nil then
  765.             ShowMessage('UnzDllExec function not found in UNZDLL.DLL');
  766.          if @GetUnzDllVersion = nil then
  767.             ShowMessage('GetZipDllVersion function not found in UNZDLL.DLL');
  768.       end
  769.       else
  770.       begin
  771.          UnzDllHandle := 0; {reset}
  772.          ShowMessage('UNZDLL.DLL not found');
  773.       end;
  774.    finally
  775.       SetErrorMode(0);
  776.    end;
  777. end;
  778.  
  779. procedure TForm1.Unload_Zip_Dll;
  780. begin
  781.    if ZipDllHandle <> 0 then
  782.       freeLibrary(ZipDllHandle);
  783.    ZipDllHandle:=0;
  784. end;
  785.  
  786. procedure TForm1.Unload_Unz_Dll;
  787. begin
  788.    if UnzDllHandle <> 0 then
  789.       freeLibrary(UnzDllHandle);
  790.    UnzDllHandle:=0;
  791. end;
  792.  
  793. end.
  794.  
  795.