home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap03 / howto06 / delphi10 / drwsutl3.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-10-22  |  103.5 KB  |  2,744 lines

  1. unit Drwsutl3;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, StdCtrls, Buttons, ExtCtrls, ShellAPI, FileCtrl, DRWSUtl1;
  8.  
  9. const
  10.   EOC_CHANGEDIR = 1;  { Error Operation Code for change directory failure }
  11.   EOC_SOURCECOPY = 2; { Error Operation Code for source copy failure      }
  12.   EOC_DESTCOPY = 3;   { Error Operation Code for destination copy failure }
  13.   EOC_DELETEFILE = 4; { Error Operation Code for file delete failure      }
  14.   EOC_DELETEDIR = 5;  { Error Operation Code for directory delete failure }
  15.   EOC_RENAMEFILE = 6; { Error Operation Code for renaming failure         }
  16.   EOC_MAKEDIR = 7;    { Error Operation Code for MkDir failure            }
  17.   EOC_SETATTR = 8;    { Error Operation Code for Set Attributes failure   }
  18.  
  19.   FAC_COPY = 1;       { File Action Code for recursive copying            }
  20.   FAC_MOVE = 2;       { File Action Code for recursive moving             }
  21.   FAC_DELETE = 3;     { File Action Code for recursive deletion           }
  22. type
  23.   { This is a descendant of TFileListbox }
  24.   { Which puts icons of files into the   }
  25.   { Objects array rather than the stand- }
  26.   { ard bitmaps.                         }
  27.   TIconFileListBox = class( TFileListBox )
  28.   public
  29.     { public methods and data }
  30.     procedure ReadFileNames; override;
  31.     function GetNextSelection( SourceDirectory : String;
  32.               var CurrentItem : Integer ) : String;
  33.     constructor Create(AOwner : TComponent); override; { override create    }
  34.     procedure TheDblClick( Sender : TObject );{ This holds override dblclick }
  35.   end;
  36.   TFileWorkBench = class( TComponent )
  37.   public
  38.     GlobalError        : Integer;  { This is used by FMXUCopyFile for er code }
  39.     GlobalErrorType    : Integer;  { This holds the Operation code            }
  40.     function ForceTrailingBackSlash( const TheFileName : String ) : String;
  41.     function StripNonRootTrailingBackSlash(
  42.               const TheFileName : String ) : String;
  43.     procedure GetFileAttributes( TheFile : String; var IsDirectory , IsArchive ,
  44.                 IsVolumeID , IsHidden , IsReadOnly , IsSysFile : Boolean );
  45.     procedure HandleIOException( TheOpCode : Integer; ThePath : String;
  46.                                  TheMessage : String; TheCode : Integer );
  47.     procedure HandleDOSError( TheOpCode : Integer; ThePath : String;
  48.                 TheCode : Integer );
  49.     function CopyFile( TargetPath ,
  50.                DestinationPath : String ) : Boolean;
  51.     procedure ChangeTheDirectory( NewPath : String );
  52.     procedure ChangeTheDriveAndDirectory( NewDrive : Integer );
  53.     procedure CopyTheFile( OldPath , NewPath : String );
  54.     procedure MoveTheFile( OldPath , NewPath : String );
  55.     procedure DeleteTheFile( ThePath : String );
  56.     procedure RenameTheFile( OldPath , NewName : String );
  57.     procedure CreateNewDirectory( NewPath : String );
  58.     procedure RemoveDirectory( ThePath : String );
  59.     procedure SetFileAttributes( TheFile  : String; TheAttributes : Integer );
  60.     procedure RecursivelyCopyDirectory( OldPath , NewPath : String );
  61.     procedure RecursivelyMoveDirectory( OldPath , NewPath : String );
  62.     procedure RecursivelyDeleteDirectory( ThePath : String );
  63.     procedure HandleRecursiveAction( StartingPath , NewPath : String;
  64.                ActionCode : Integer );
  65.   end;
  66.   TFileIconPanel = class( TPanel )
  67.   private
  68.     { Private declarations }
  69.     FHighlightColor : TColor;                 { This holds bright edge bevel }
  70.     FShadowColor    : TColor;                 { This holds dark edge bevel   }
  71.     procedure TheMouseDown(Sender: TObject;
  72.       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  73.     procedure TheMouseUp(Sender: TObject;
  74.       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  75.     procedure WMLButtonDblClk(var Message: TWMLButtonDblClk);
  76.      message WM_LBUTTONDBLCLK;
  77.     procedure TheDragOver(Sender, Source: TObject; X,
  78.       Y: Integer; State: TDragState; var Accept: Boolean);
  79.     procedure TheDragDrop(Sender, Source: TObject; X,
  80.       Y: Integer);
  81.   protected                                   { event method procedure.      }
  82.     { Protected declarations }
  83.     procedure Paint; override;                { This allows custom painting  }
  84.   public
  85.     { Public declarations }
  86.     FTheIcon : TIcon;                         { This is the display icon    }
  87.     FTheName : String;                        { This is the filename        }
  88.     FTheLabel : TLabel;                       { This is the display label   }
  89.     Selected : Boolean;                       { This holds selection status }
  90.     constructor Create(AOwner : TComponent); override; { override create    }
  91.     procedure Initialize( PanelX              ,             { Left          }
  92.                           PanelY              ,             { Top           }
  93.                           PanelWidth          ,             { Width         }
  94.                           PanelHeight         ,             { Height        }
  95.                           PanelBevelWidth     ,             { Bevel Width   }
  96.                           LabelFontSize         : Integer;  { Font size     }
  97.                           PanelColor          ,             { Main color    }
  98.                           PanelHighlightColor ,             { Bright color  }
  99.                           PanelShadowColor    ,             { Dark color    }
  100.                           LabelTextColor        : TColor;   { Text color    }
  101.                           TheFilename         ,             { Filename      }
  102.                           LabelFontName         : String;   { Font name     }
  103.                           LabelFontStyle        : TFontStyles;  { Font style}
  104.                           ExtraData             : Integer       );  { Drive }
  105.     destructor Destroy; override;             { override destroy to free    }
  106.   end;
  107.   TFileIconPanelScrollBox = class( TScrollBox )
  108.   public
  109.     { Public methods and data }
  110.     TheFWB              : TFileWorkBench; { Used for file manipulation         }
  111.     IconsNeedRefreshing : Boolean;                   { Flag to redo display    }
  112.     TheIconSize        : Integer;   { Holds Individual Icon size               }
  113.     TheIconSpacing     : Integer;   { Holds total icon footprint               }
  114.     MaxIconsInARow     : Integer;   { Set for screen size.                     }
  115.     TheStoredHandle    : HWnd;
  116.     TheParentForm      : TForm;
  117.     procedure Update;                                { Called to reset display }
  118.     constructor Create( AOwner : TComponent ); override;  { Override inherited }
  119.     procedure ClearTheFIPs;                          { Clears the FIPs safely  }
  120.     procedure AddDriveIcons( var XCounter , YCounter : Integer ); { Add drives }
  121.     procedure GetColorsForFileIcon( TheFile : String;
  122.                var BC , HC , SC , TC : TColor );
  123.     procedure GetIconsForEntireDirectory( TargetPath  : String );
  124.     function GetNextSelection( SourceDirectory : String;
  125.               var CurrentItem : Integer ) : String;
  126.     procedure DisplayRecursiveSearchResults(
  127.       TheStartingDirectory : String );
  128.   end;
  129.   TIOManager = class( TComponent )
  130.   public
  131.     Parent : TForm;
  132.     WhichButton : TMouseButton;
  133.     WhichState  : TShiftState;
  134.     CLState ,
  135.     NLState ,
  136.     SLState   : Boolean;
  137.     function IsCapsLockDown : Boolean;
  138.     function ISNumLockDown : Boolean;
  139.     function IsScrollLockDown : Boolean;
  140.     procedure InitLocks;
  141.     procedure ReadLocks( var TheCL , TheNL , TheSL : Boolean );
  142.     procedure SetLocks( TheCL , TheNL , TheSL : Boolean );
  143.     function WasLeftPressed : Boolean;
  144.     function WasRightPressed : Boolean;
  145.     function WasMiddlePressed : Boolean;
  146.     function WasALTPressed : Boolean;
  147.     function WasSHIFTPressed : Boolean;
  148.     function WasCTRLPressed : Boolean;
  149.     procedure OnF1Pressed(Sender: TObject; var Key: Word;
  150.      Shift: TShiftState);
  151.     procedure OnF2Pressed(Sender: TObject; var Key: Word;
  152.      Shift: TShiftState);
  153.     procedure OnF3Pressed(Sender: TObject; var Key: Word;
  154.      Shift: TShiftState);
  155.     procedure OnF4Pressed(Sender: TObject; var Key: Word;
  156.      Shift: TShiftState);
  157.     procedure OnF5Pressed(Sender: TObject; var Key: Word;
  158.      Shift: TShiftState);
  159.     procedure OnF6Pressed(Sender: TObject; var Key: Word;
  160.      Shift: TShiftState);
  161.     procedure OnF7Pressed(Sender: TObject; var Key: Word;
  162.      Shift: TShiftState);
  163.     procedure OnF8Pressed(Sender: TObject; var Key: Word;
  164.      Shift: TShiftState);
  165.     procedure OnF9Pressed(Sender: TObject; var Key: Word;
  166.      Shift: TShiftState);
  167.     procedure OnF10Pressed(Sender: TObject; var Key: Word;
  168.      Shift: TShiftState);
  169.     procedure OnF11Pressed(Sender: TObject; var Key: Word;
  170.      Shift: TShiftState);
  171.     procedure OnF12Pressed(Sender: TObject; var Key: Word;
  172.      Shift: TShiftState);
  173.  end;
  174.   { This procedure gets an icon for a file using FindExecutable  }
  175.   { and ExtractIcon. (assumes file/dir is passed)                }
  176.   procedure GetIconForFile( TheName : String; var TheIcon : TIcon );
  177.   { This procedure spaces out the bitbtn components on a tpanel }
  178.   procedure SpacePanelButtons( WhichPanel : TPanel );
  179.     procedure FMXUCopyFile(const FileName, DestName: String; var GlobalErrorType ,
  180.                GlobalErrorCode : Integer );
  181.  
  182. var TheIOManager : TIOManager;
  183.     GlobalAbortFlag : Boolean;
  184.  
  185. implementation
  186. {$R DRWSUTL3.RES}                 { Import custom resource file }
  187. uses UFMGR15;
  188.  
  189. { It has been edited to return viable error codes!             }
  190. procedure FMXUCopyFile(const FileName, DestName: String; var GlobalErrorType ,
  191.             GlobalErrorCode : Integer );
  192. var
  193.   CopyBuffer: Pointer; { buffer for copying }
  194.   BytesCopied: Longint;
  195.   TheAttr : Integer;
  196.   Source, Dest: Integer; { handles }
  197. const
  198.   ChunkSize: Longint = 8192; { copy in 8K chunks }
  199. begin
  200.   GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
  201.   Source := FileOpen(FileName, fmShareDenyWrite); { open source file }
  202.   if Source < 0 then
  203.   begin  { error creating source file }
  204.     GlobalErrorType := EOC_SOURCECOPY;
  205.     GlobalErrorCode := -IOResult;
  206.     if GlobalErrorCode = 0 then GlobalErrorCode := -157;
  207.     FreeMem( CopyBuffer, ChunkSize );
  208.     exit;
  209.   end;
  210.   Dest := FileCreate(DestName); { create output file; overwrite existing }
  211.   if Dest < 0 then
  212.   begin  { error creating destination file }
  213.     FileClose( Source );
  214.     GlobalErrorType := EOC_DESTCOPY;
  215.     GlobalErrorCode := -IOResult;
  216.     if GlobalErrorCode = 0 then GlobalErrorCode := -159;
  217.     FreeMem( CopyBuffer , ChunkSize );
  218.     exit;
  219.   end;
  220.   {$I-}
  221.   repeat
  222.     BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk}
  223.     if BytesCopied > 0 then { if we read anything... }
  224.     FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
  225.   until BytesCopied < ChunkSize; { until we run out of chunks }
  226.   {$I+}
  227.   GlobalErrorCode := -IOResult;  { get any error code which happens during copying }
  228.   FileClose(Dest); { close the destination file }
  229.   FileClose(Source); { close the source file }
  230.   FreeMem(CopyBuffer, ChunkSize); { free the buffer }
  231. end;
  232.  
  233. { This procedure spaces out the bitbtn components on a tpanel }
  234. procedure SpacePanelButtons( WhichPanel : TPanel );
  235. var TheCalculatedSpacing     ,            { Holds primary spacing }
  236.     TheFullCalculatedSpacing   : Integer; { Holds full spacing    }
  237.     Counter_1                  : Integer; { Loop counter          }
  238.     TotalIBs                   : Integer; { Gets total buttons    }
  239. begin
  240.   { Set up spacing values }
  241.   TotalIBs := WhichPanel.ControlCount;
  242.   TheCalculatedSpacing := (( WhichPanel.Width - 6 - ( TotalIbs * 49 ))
  243.    div ( TotalIbs + 1 ));
  244.   TheFullCalculatedSpacing := TheCalculatedSpacing + 49;
  245.   { Loop through all imported buttons and set their Left values }
  246.   for Counter_1 := 1 to WhichPanel.ControlCount do
  247.   begin
  248.     if Counter_1 = 1 then
  249.     begin
  250.       TBitBtn( WhichPanel.Controls[ Counter_1 - 1 ] ).Left := 3 +
  251.        TheCalculatedSpacing;
  252.     end
  253.     else
  254.     begin
  255.       TBitBtn( WhichPanel.Controls[ Counter_1 - 1 ] ).Left := 3 +
  256.        (( Counter_1 - 1 ) * TheFullCalculatedSpacing ) + TheCalculatedSpacing;
  257.     end;
  258.   end;
  259. end;
  260.  
  261. { This procedure gets an icon for a file using FindExecutable  }
  262. { and ExtractIcon. (assumes file/dir is passed)                }
  263. procedure GetIconForFile( TheName : String; var TheIcon : TIcon );
  264. var TheExt           : String; { File extension holder }
  265.     TheOtherPChar  ,           { Windows ASCIIZ string }
  266.     TheResultPChar ,           { Windows ASCIIZ string }
  267.     ThePChar         : PChar;  { Windows ASCIIZ string }
  268. begin
  269.   { Check for directory and if so get directory icon from RES file }
  270.   if (( FileGetAttr( TheName ) and faDirectory ) = faDirectory ) then
  271.   begin
  272.     { Set up the PChar to communicate with Windows }
  273.     GetMem( TheOtherPChar , 255 );
  274.     { Convert Pascal-style string to ASCIIZ Pchar }
  275.     StrPCopy( TheOtherPChar , 'DIRECTORY' );
  276.     { Use API call to return icon handle of Icon Resource in FILECTRL.RES }
  277.     TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  278.     { Release memory from PChar }
  279.     FreeMem( TheOtherPChar , 255 );
  280.     { Leave }
  281.     exit;
  282.   end;
  283.   { Assume archive file; get its extension }
  284.   TheExt := Uppercase( ExtractFileExt( TheName ));
  285.   { If not an executable/image file then use FindExecutable to get icon }
  286.   if (( TheExt <> '.EXE' ) and ( TheExt <> '.BAT' ) and
  287.       ( TheExt <> '.PIF' ) and ( TheExt <> '.COM' )) then
  288.   begin
  289.     { Grab three chunks of memory }
  290.     GetMem( TheOtherPChar , 255 );
  291.     GetMem( TheResultPChar , 255 );
  292.     GetMem( ThePChar , 255 );
  293.     { Set up the name and its directory in Windows string formats }
  294.     StrPCopy( ThePChar, TheName );
  295.     StrPCopy( TheOtherPChar , ExtractFilePath( TheName ));
  296.     { Use FindExecutable API call to get path and name of owning file }
  297.     if FindExecutable( ThePChar , TheOtherPChar , TheResultPChar ) > 31 then
  298.     begin
  299.       { If get a result of 32 or more then try to get first icon of owner }
  300.       { Using ExtractIcon API call; 0 indicates first icon.               }
  301.       TheIcon.Handle := ExtractIcon( hInstance , TheResultPchar , 0 );
  302.       { If a handle is 0 then no icon in owner, get default icon from RES file }
  303.       if TheIcon.Handle = 0 then
  304.       begin
  305.         GetMem( TheOtherPChar , 255 );
  306.         StrPCopy( TheOtherPChar , 'NOICON' );
  307.         TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  308.         FreeMem( TheOtherPChar , 255 );
  309.         exit;
  310.       end;
  311.     end
  312.     else
  313.     { if no assigned executable, then get default icon from RES file }
  314.     begin
  315.       GetMem( TheOtherPChar , 255 );
  316.       StrPCopy( TheOtherPChar , 'NOICON' );
  317.       TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  318.       FreeMem( TheOtherPChar , 255 );
  319.       exit;
  320.     end;
  321.     FreeMem( TheOtherPChar , 255 );
  322.     FreeMem( TheResultPChar , 255 );
  323.     FreeMem( ThePChar , 255 );
  324.   end
  325.   else
  326.   { Assume Windows Executable file, so get icon from it with ExtractIcon API }
  327.   begin
  328.     GetMem( ThePChar , 255 );
  329.     StrPCopy( ThePChar , TheName );
  330.     { If no icons in file then get default icon (note use FFFF for -1) }
  331.     if ExtractIcon( hInstance , ThePchar , 65535 ) = 0 then
  332.     begin
  333.       Freemem( ThePChar , 255 );
  334.       GetMem( TheOtherPChar , 255 );
  335.       StrPCopy( TheOtherPChar , 'NOICON' );
  336.       TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  337.       FreeMem( TheOtherPChar , 255 );
  338.       exit;
  339.     end
  340.     else
  341.     begin
  342.       { Try to get first icon for file }
  343.       TheIcon.Handle := ExtractIcon( hInstance , ThePChar , 0 );
  344.       FreeMem( ThePChar , 255 );
  345.       { If handle is 0 invalid icon format so use default from RES file }
  346.       if TheIcon.Handle = 0 then
  347.       begin
  348.         GetMem( TheOtherPChar , 255 );
  349.         StrPCopy( TheOtherPChar , 'NOICON' );
  350.         TheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  351.         FreeMem( TheOtherPChar , 255 );
  352.         exit;
  353.       end;
  354.     end;
  355.   end;
  356. end;
  357.  
  358. { This function returns true if CAPSLOCK is down }
  359. function TIoManager.IsCapsLockDown : Boolean;
  360. begin
  361.   if CLState then result := true else result := false;
  362. end;
  363.  
  364. { This function returns true if NUMLOCK is down }
  365. function TIoManager.ISNumLockDown : Boolean;
  366. begin
  367.   if NLState then result := true else result := false;
  368. end;
  369.  
  370. { This function returns true if SCROLLLOCK is down }
  371. function TIoManager.IsScrollLockDown : Boolean;
  372. begin
  373.   if SLState then result := true else result := false;
  374. end;
  375.  
  376. { this function gets the values for CLState, NLState, and SLState }
  377. procedure TIoManager.InitLocks;
  378. var TheKeys : TKeyboardState;
  379. begin
  380.   GetKeyBoardState( TheKeys );
  381.   CLState := (( TheKeys[ VK_Capital ] mod 2 ) = 1 );
  382.   NLState := (( TheKeys[ VK_Numlock ] mod 2 ) = 1 );
  383.   CLState := (( TheKeys[ VK_Scroll ] mod 2 ) = 1 );
  384. end;
  385.  
  386. { This procedure returns the state of the three lock variables }
  387. procedure TIoManager.ReadLocks( var TheCL , TheNL , TheSL : Boolean );
  388. begin
  389.   TheCL := CLState;
  390.   TheNL := NLState;
  391.   TheSL := SLState;
  392. end;
  393.  
  394. { This procedure sets the state of the three lock variables to the imported vals }
  395. procedure TIoManager.SetLocks( TheCL , TheNL , TheSL : Boolean );
  396. var TheKeys : TKeyBoardState;
  397. begin
  398.   GetKeyBoardState( TheKeys );
  399.   CLState := TheCL;
  400.   NLState := TheNL;
  401.   SLState := TheSL;
  402.   if ClState then TheKeys[ VK_Capital ] := 1 else
  403.    TheKeys[ VK_Capital ] := 0;
  404.   if NLState then TheKeys[ VK_Numlock ] := 1 else
  405.    TheKeys[ VK_Numlock ] := 0;
  406.   if SLState then TheKeys[ VK_Scroll ] := 1 else
  407.    TheKeys[ VK_Scroll ] := 0;
  408.   SetKeyBoardState( TheKeys );
  409. end;
  410.  
  411. { This procedure handles pressing of F1 for CCFileManagerForm }
  412. procedure TIoManager.OnF1Pressed(Sender: TObject; var Key: Word;
  413.   Shift: TShiftState);
  414. begin
  415.   MessageDlg( 'Help not implemented!' , mtInformation,[mbok],0);
  416. end;
  417.  
  418. { This procedure handles pressing of F2 for CCFileManagerForm }
  419. procedure TIoManager.OnF2Pressed(Sender: TObject; var Key: Word;
  420.   Shift: TShiftState);
  421. begin
  422.   TCCFileMgrForm( Parent ).BitBtn1Click( Sender );
  423. end;
  424.  
  425. { This procedure handles pressing of F3 for CCFileManagerForm }
  426. procedure TIoManager.OnF3Pressed(Sender: TObject; var Key: Word;
  427.   Shift: TShiftState);
  428. begin
  429.   TCCFileMgrForm( Parent ).BitBtn2Click( Sender );
  430. end;
  431.  
  432. { This procedure handles pressing of F4 for CCFileManagerForm }
  433. procedure TIoManager.OnF4Pressed(Sender: TObject; var Key: Word;
  434.   Shift: TShiftState);
  435. begin
  436.   TCCFileMgrForm( Parent ).BitBtn3Click( Sender );
  437. end;
  438.  
  439. { This procedure handles pressing of F5 for CCFileManagerForm }
  440. procedure TIoManager.OnF5Pressed(Sender: TObject; var Key: Word;
  441.   Shift: TShiftState);
  442. begin
  443.   TCCFileMgrForm( Parent ).BitBtn4Click( Sender );
  444. end;
  445.  
  446. { This procedure handles pressing of F6 for CCFileManagerForm }
  447. procedure TIoManager.OnF6Pressed(Sender: TObject; var Key: Word;
  448.   Shift: TShiftState);
  449. begin
  450.   TCCFileMgrForm( Parent ).BitBtn5Click( Sender );
  451. end;
  452.  
  453. { This procedure handles pressing of F7 for CCFileManagerForm }
  454. procedure TIoManager.OnF7Pressed(Sender: TObject; var Key: Word;
  455.   Shift: TShiftState);
  456. begin
  457.   TCCFileMgrForm( Parent ).BitBtn9Click( Sender );
  458. end;
  459.  
  460. { This procedure handles pressing of F8 for CCFileManagerForm }
  461. procedure TIoManager.OnF8Pressed(Sender: TObject; var Key: Word;
  462.   Shift: TShiftState);
  463. begin
  464.   TCCFileMgrForm( Parent ).BitBtn6Click( Sender );
  465. end;
  466.  
  467. { This procedure handles pressing of F9 for CCFileManagerForm }
  468. procedure TIoManager.OnF9Pressed(Sender: TObject; var Key: Word;
  469.   Shift: TShiftState);
  470. begin
  471.   TCCFileMgrForm( Parent ).Update;
  472. end;
  473.  
  474. { This procedure handles pressing of F10 for CCFileManagerForm }
  475. procedure TIoManager.OnF10Pressed(Sender: TObject; var Key: Word;
  476.   Shift: TShiftState);
  477. begin
  478.   TCCFileMgrForm( Parent ).BitBtn7Click( Sender );
  479. end;
  480.  
  481. { This procedure handles pressing of F11 for CCFileManagerForm }
  482. procedure TIoManager.OnF11Pressed(Sender: TObject; var Key: Word;
  483.   Shift: TShiftState);
  484. begin
  485.   TCCFileMgrForm( Parent ).BitBtn8Click( Sender );
  486. end;
  487.  
  488. { This procedure handles pressing of F12 for CCFileManagerForm }
  489. procedure TIoManager.OnF12Pressed(Sender: TObject; var Key: Word;
  490.   Shift: TShiftState);
  491. begin
  492.   TCCFileMgrForm( Parent ).BitBtn10Click( Sender );
  493. end;
  494.  
  495. { Returns True if the Left Button was pressed in the last mouse operation }
  496. function TIOManager.WasLeftPressed : Boolean;
  497. begin
  498.   if ( mbLeft = WhichButton ) then WasLeftPressed := true else
  499.    WasLeftPressed := false;
  500. end;
  501.  
  502. { Returns true if the Right Button was pressed in the last mouse operation }
  503. function TIOManager.WasRightPressed : Boolean;
  504. begin
  505.   if mbRight = WhichButton then WasRightPressed := true else
  506.    WasRightPressed := false;
  507. end;
  508.  
  509. { Returns true if the Middle Button was pressed in the last mouse operation }
  510. function TIOManager.WasMiddlePressed : Boolean;
  511. begin
  512.   if mbMiddle = WhichButton then WasMiddlePressed := true else
  513.    WasMiddlePressed := false;
  514. end;
  515.  
  516. { Returns true if the ALT key was down during the last IO operation }
  517. function TIOManager.WasALTPressed : Boolean;
  518. begin
  519.   if ssAlt in WhichState then WasALTPressed := true else
  520.    WasALTPressed := false;
  521. end;
  522.  
  523. { Returns true if either SHIFT key was down during the last IO operation }
  524. function TIOManager.WasSHIFTPressed : Boolean;
  525. begin
  526.   if ssShift in WhichState then WasSHIFTPressed := true else
  527.    WasSHIFTPressed := false;
  528. end;
  529.  
  530. { Returns true if the Control Key was down during the last IO operation }
  531. function TIOManager.WasCTRLPressed : Boolean;
  532. begin
  533.   if ssCtrl in WhichState then WasCTRLPressed := true else
  534.    WasCTRLPressed := false;
  535. end;
  536.  
  537.  
  538. { This procedure does a fully error-trapped change directory }
  539. procedure TFileWorkBench.ChangeTheDirectory( NewPath : String );
  540. var CurrentDirectory : String;
  541. begin
  542.   if NewPath = '..' then
  543.   begin { Back up one level }
  544.     {$I+}
  545.     try
  546.       { Find the current directory }
  547.       GetDir( 0 , CurrentDirectory );
  548.       { Use EFP to move up one level }
  549.       CurrentDirectory := ExtractFilePath( CurrentDirectory );
  550.       { Strip trailing \ if not root }
  551.       CurrentDirectory := StripNonRootTrailingBackSlash( CurrentDirectory );
  552.       { Try the change to the new drive }
  553.       ChDir( CurrentDirectory );
  554.     except
  555.       { if any exception occurs instantiate exception and show }
  556.       On E:EInOutError do
  557.       begin
  558.         { Call custom error display/lookup procedure }
  559.         HandleIOException( EOC_CHANGEDIR , CurrentDirectory ,
  560.          E.Message , E.ErrorCode );
  561.       end;
  562.     end;
  563.   end
  564.   else
  565.   begin { Change to explicit path }
  566.     {$I+}
  567.     try
  568.       { Get target directory path }
  569.       CurrentDirectory := NewPath;
  570.       { Strip trailing \ if not root }
  571.       CurrentDirectory := StripNonRootTrailingBackSlash( CurrentDirectory );
  572.       { Try the change to the new drive }
  573.       ChDir( CurrentDirectory );
  574.     except
  575.       { if any exception occurs instantiate exception and show }
  576.       On E:EInOutError do
  577.       begin
  578.         { Call custom error display/lookup procedure }
  579.         HandleIOException( EOC_CHANGEDIR , CurrentDirectory ,
  580.          E.Message , E.ErrorCode );
  581.       end;
  582.     end;
  583.   end;
  584. end;
  585.  
  586. { This procedure does a fully error-trapped change directory }
  587. procedure TFileWorkBench.ChangeTheDriveAndDirectory( NewDrive : Integer );
  588. var CurrentDirectory : String;
  589. begin
  590.   {$I+}
  591.   try
  592.     { Find the working directory on new drive }
  593.     GetDir( NewDrive , CurrentDirectory );
  594.     { Try the change to the new drive }
  595.     ChDir( CurrentDirectory );
  596.   except
  597.     { if any exception occurs instantiate exception and show }
  598.     On E:EInOutError do
  599.     begin
  600.       { Call custom error display/lookup procedure }
  601.       HandleIOException( EOC_CHANGEDIR , CurrentDirectory ,
  602.        E.Message , E.ErrorCode );
  603.     end;
  604.   end;
  605. end;
  606.  
  607. { This procedure copies a single file with error trapping }
  608. procedure TFileWorkBench.CopyTheFile( OldPath , NewPath : String );
  609. var AResult : Boolean; { Internal data flag }
  610. begin
  611.   { If Copyfile returns false an error occurred }
  612.   AResult := CopyFile( OldPath , NewPath +
  613.    ExtractFileName( OldPath ));
  614.   { Display meaningful error message }
  615.   if not AResult then HandleDOSError( GlobalErrorType , OldPath, GlobalError );
  616. end;
  617.  
  618. { This procedure moves a file by copying and delete it }
  619. procedure TFileWorkBench.MoveTheFile( OldPath , NewPath : String );
  620. var AResult : Boolean; { Internal data flag }
  621.     TheFile : File;    { Use to get errors  }
  622. begin
  623.   { If Copyfile returns false an error occurred }
  624.   AResult := CopyFile( OldPath , NewPath +
  625.     ExtractFileName( OldPath ));
  626.   { Display meaningful error message }
  627.   if not AResult then HandleDOSError( GlobalErrorType ,
  628.     OldPath , GlobalError );
  629.   { After valid copying, delete source file }
  630.   {$I+}
  631.   if AResult then try
  632.     { Use this trick to get valid exception handling }
  633.     AssignFile( TheFile , OldPath );
  634.     { Use erase because Deletefile doesn't give exceptions! }
  635.     Erase( TheFile );
  636.   except
  637.     { if any exception occurs instantiate exception and show }
  638.     On E:EInOutError do
  639.     begin
  640.       { Call custom error display/lookup procedure }
  641.       HandleIOException( EOC_DELETEFILE , OldPath ,
  642.        E.Message , E.ErrorCode );
  643.     end;
  644.   end;
  645. end;
  646.  
  647. { This procedure safely deletes a single file }
  648. procedure TFileWorkBench.DeleteTheFile( ThePath : String );
  649. var TheFile : File; { Internal file handle }
  650. begin
  651.   {$I+}
  652.   try
  653.     { Use this trick to get valid exception handling }
  654.     AssignFile( TheFile , ThePath );
  655.     { Use erase because Deletefile doesn't give exceptions! }
  656.     Erase( TheFile );
  657.   except
  658.     { if any exception occurs instantiate exception and show }
  659.     On E:EInOutError do
  660.     begin
  661.       { Call custom error display/lookup procedure }
  662.       HandleIOException( EOC_DELETEFILE , ThePath ,
  663.        E.Message , E.ErrorCode );
  664.     end;
  665.   end;
  666. end;
  667.  
  668. { This procedure renames a file with full error trapping }
  669. procedure TFileWorkBench.RenameTheFile( OldPath , NewName : String );
  670. var TheFile : File; { Internal file handle }
  671. begin
  672.   {$I+}
  673.   try
  674.     { Use this trick to get valid exception handling }
  675.     AssignFile( TheFile , OldPath );
  676.     { Use this because RenameFile doesn't give exceptions! }
  677.     Rename( TheFile , NewName );
  678.   except
  679.     { if any exception occurs instantiate exception and show }
  680.     On E:EInOutError do
  681.     begin
  682.       { Call custom error display/lookup procedure }
  683.       HandleIOException( EOC_RENAMEFILE , OldPath  ,
  684.        E.Message , E.ErrorCode );
  685.     end;
  686.   end;
  687. end;
  688.  
  689. { This procedure creates a new directory with full error trapping }
  690. procedure TFileWorkBench.CreateNewDirectory( NewPath : String );
  691. begin
  692.   {$I+}
  693.   try
  694.     Mkdir( NewPath );
  695.   except
  696.     { if any exception occurs instantiate exception and show }
  697.     On E:EInOutError do
  698.     begin
  699.       { Call custom error display/lookup procedure }
  700.       HandleIOException( EOC_MAKEDIR , NewPath  ,
  701.        E.Message , E.ErrorCode );
  702.     end;
  703.   end;
  704. end;
  705.  
  706. { This procedure remove a directory with full error trapping }
  707. procedure TFileWorkBench.RemoveDirectory( ThePath : String );
  708. begin
  709.   {$I+}
  710.   try
  711.     Rmdir( ThePath );
  712.   except
  713.     { if any exception occurs instantiate exception and show }
  714.     On E:EInOutError do
  715.     begin
  716.       { Call custom error display/lookup procedure }
  717.       HandleIOException( EOC_DELETEDIR , ThePath  ,
  718.        E.Message , E.ErrorCode );
  719.     end;
  720.   end;
  721. end;
  722.  
  723. { Use this to set the attributes of a file with error trapping }
  724. procedure TFileWorkBench.SetFileAttributes( TheFile  : String;
  725.            TheAttributes : Integer );
  726. var TheResult : Integer; { Holds error code if any }
  727. begin
  728.   { Attempt to set the attributes }
  729.   TheResult := FileSetAttr( TheFile , TheAttributes );
  730.   { if negative number error, so signal }
  731.   if TheResult < 0 then
  732.    HandleDOSError( EOC_SETATTR , TheFile , -TheResult );
  733. end;
  734.  
  735. { This procedure recursively copies a directory to a new path }
  736. procedure TFileWorkBench.RecursivelyCopyDirectory( OldPath , NewPath : String );
  737. var TheDir : String; { Holds source directory }
  738. begin
  739.   { Get the source directory to copy }
  740.   TheDir := ExtractFileName( OldPath );
  741.   { Force a backslash to the newpath variable }
  742.   NewPath := ForceTrailingBackSlash( NewPath );
  743.   { Add the source directory to the target path }
  744.   NewPath := NewPath + TheDir;
  745.   { Create a new directory with the new name }
  746.   CreateNewDirectory( NewPath );
  747.   { Force a backslash for compatibility }
  748.   NewPath := FOrcetrailingBackSlash( NewPath );
  749.   { Do the recursive call }
  750.   HandleRecursiveAction( OldPath , NewPath , FAC_COPY );
  751. end;
  752.  
  753. { This procedure recursively moves a directory tree }
  754. procedure TFileWorkBench.RecursivelyMoveDirectory( OldPath , NewPath : String );
  755. var TheDir    : String; { Holds source directory  }
  756.     SavedPath : String; { Holds saved dir to kill }
  757. begin
  758.   { Get the source directory to move }
  759.   TheDir := ExtractFileName( OldPath );
  760.   { Force a backslash to the newpath variable }
  761.   NewPath := ForceTrailingBackSlash( NewPath );
  762.   { Save the starting path just in case }
  763.   SavedPath := OldPath;
  764.   { Add the source directory to the target path }
  765.   NewPath := NewPath + TheDir;
  766.   { Create a new directory with the new name }
  767.   CreateNewDirectory( NewPath );
  768.   { Force a backslash for compatibility }
  769.   NewPath := FOrcetrailingBackSlash( NewPath );
  770.   { Do the recursive call }
  771.   HandleRecursiveAction( OldPath , NewPath , FAC_MOVE );
  772.   { Remove the source directory }
  773.   RemoveDirectory( SavedPath );
  774. end;
  775.  
  776. { This procedure handles recursively deleting an entire directory tree }
  777. procedure TFileWorkBench.RecursivelyDeleteDirectory( ThePath : String );
  778. begin
  779.   HandleRecursiveAction( ThePath , '' , FAC_DELETE );
  780. end;
  781.  
  782.  
  783. { This is the generic routine to copy, move, and delete whole directory trees }
  784. procedure TFileWorkBench.HandleRecursiveAction( StartingPath , NewPath : String;
  785.            ActionCode : Integer );
  786. { VITAL!!! These variables MUST be local for recursrion to work! }
  787. var
  788.     Finished        : Boolean;         { Loop flag              }
  789.     TheSR           : TSearchRec;      { Searchrecord for FF/FN }
  790.     TheResult       : Integer;         { return variable        }
  791.     TargetPath ,
  792.     FileMask   ,
  793.     TheWorkingDirectory ,
  794.     TheStoredWorkingDirectory ,
  795.     ModifiedDirectory  : String;       { path for FF/FN         }
  796.     TheFIP          : TFileIconPanel;  { generic FIP holder     }
  797.     ButtonColor   ,                    { main panel color       }
  798.     ButtonHLColor ,                    { bright panel color     }
  799.     ButtonSColor  ,                    { dark panel color       }
  800.     Textcolor       : TColor;          { label text color       }
  801.     TheFile         : File;
  802.  
  803. begin
  804.   { Set up the initial variables }
  805.   Finished := false;
  806.   TheWorkingDirectory := StartingPath;
  807.   TheStoredWorkingDirectory := TheWorkingDirectory;
  808.   TheWorkingDirectory := TheWorkingDirectory + '\*.*';
  809.   TargetPath := ExtractFilePath( TheWorkingDirectory );
  810.   { Make the call to FindFirst set to get any file }
  811.   TheResult := FindFirst( TheWorkingDirectory , faAnyFile , TheSR );
  812.   { loop through all files in the directory and delete them }
  813.   while not Finished do
  814.   begin
  815.     { Make call to FindNext, using only SearchRecord from FindFirst }
  816.     TheResult := FindNext( TheSR );
  817.     { A -1 result means no more files so exit }
  818.     if TheResult < 0 then finished := true else
  819.     begin
  820.       if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory )
  821.        <> faDirectory ) then
  822.       begin { A File }
  823.         case ActionCode of
  824.           FAC_COPY :
  825.               begin
  826.                 CopyTheFile( TargetPath + TheSR.Name , NewPath );
  827.               end;
  828.           FAC_MOVE :
  829.               begin
  830.                 MoveTheFile( TargetPath + TheSR.Name , NewPath );
  831.               end;
  832.           FAC_DELETE :
  833.               begin { Delete }
  834.                 if MessageDlg( 'Delete file ' + TargetPath + TheSR.Name + '?',
  835.                    mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  836.                     DeleteTheFile( TargetPath + TheSR.Name );
  837.               end;
  838.         end;
  839.       end;
  840.     end;
  841.   end;
  842.   { Call FindClose for Windows NT/Windows 95 compatibility }
  843.   FindClose( TheSR );
  844.   { Set up the variables to do recursive calls on all directories}
  845.   Finished := false;
  846.   ModifiedDirectory := TheStoredWorkingdirectory + '\*.*';
  847.   { Make the call to FindFirst set to get any file, ignore result }
  848.   TheResult := FindFirst( ModifiedDirectory , faDirectory , TheSR );
  849.   while not Finished do
  850.   begin
  851.     { Make call to FindNext, using only SearchRecord from FindFirst }
  852.     TheResult := FindNext( TheSR );
  853.     { A -1 result means no more files so exit }
  854.     if TheResult < 0 then
  855.       finished := true
  856.     else
  857.     begin
  858.       if TheSR.Name <> '..' then { Ignore backup in this case }
  859.       begin
  860.         if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory )
  861.          = faDirectory ) then
  862.         begin
  863.           { Send in the new directory name }
  864.           ModifiedDirectory := TheStoredWorkingDirectory  + '\' +
  865.            TheSR.Name;
  866.           { Reproduce directory structure for recursion in copy/move }
  867.           NewPath := NewPath + TheSR.Name;
  868.           case ActionCode of
  869.             FAC_COPY , FAC_MOVE :
  870.                begin { Create ahead for move and copy }
  871.                  { Make the new directory for moving and copying }
  872.                  CreateNewDirectory( NewPath );
  873.                  { Force a backslash for compatibility }
  874.                  NewPath := ForceTrailingBackSlash( NewPath );
  875.                end;
  876.             FAC_DELETE :
  877.                begin  { No prior action needed for Delete }
  878.                end;
  879.           end;
  880.           { Do the recursive call }
  881.           HandleRecursiveAction( ModifiedDirectory , NewPath , ActionCode );
  882.           case ActionCode of
  883.             FAC_COPY :
  884.                begin { no action for copy }
  885.                end;
  886.             FAC_MOVE , FAC_DELETE :
  887.                begin  { Delete }
  888.                  { Get a confirmation }
  889.                  if MessageDlg( 'Remove Directory ' + TargetPath + TheSR.Name
  890.                   + '?', mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  891.                    RemoveDirectory( TargetPath + TheSR.Name );
  892.                end;
  893.           end;
  894.         end;
  895.       end;
  896.     end;
  897.   end;
  898. end;
  899.  
  900. { This is a generic copy routine taken from Delphi sample code }
  901. { This function calls the sample Copy code and handles errors }
  902. function TFileWorkBench.CopyFile( TargetPath ,
  903.           DestinationPath : String ) : Boolean;
  904. begin
  905.   { Set global error value to no error }
  906.   GlobalError := 0;
  907.   { Call the sample procedure to do the copy }
  908.   FMXUCopyFile( TargetPath, DestinationPath , GlobalErrorType , GlobalError );
  909.   { If no error return true else return false }
  910.   if GlobalError < 0 then CopyFile := false else
  911.    CopyFile := true;
  912. end;
  913.  
  914. { This procedure handles displaying a user-friendly Dialog box with a }
  915. { Message for Delphi IO exception errors.                             }
  916. procedure TFileWorkBench.HandleIOException( TheOpCode : Integer;
  917.            ThePath : String; TheMessage : String; TheCode : Integer );
  918. var ErrorMessageString : String;  { Holds internal data }
  919.     OperationString    : String;  { Holds internal data }
  920. begin
  921.   { clear to check for unrecognized code }
  922.   ErrorMessageString := '';
  923.   { Check against imported code }
  924.   case TheCode of
  925.     2    : ErrorMessageString := 'File not found';
  926.     3    : ErrorMessageString := 'Path not found';
  927.     4    : ErrorMessageString := 'Too many open files';
  928.     5    : ErrorMessageString := 'File access denied';
  929.     6    : ErrorMessageString := 'Invalid file handle';
  930.     12    : ErrorMessageString := 'Invalid file access code';
  931.     15    : ErrorMessageString := 'Invalid drive number';
  932.     16  : ErrorMessageString := 'Cannot remove current directory';
  933.     17    : ErrorMessageString := 'Cannot rename across drives';
  934.     100    : ErrorMessageString := 'Disk read error';
  935.     101    : ErrorMessageString := 'Disk write error';
  936.     102    : ErrorMessageString := 'File not assigned';
  937.     103    : ErrorMessageString := 'File not open';
  938.     104    : ErrorMessageString := 'File not open for input';
  939.     105    : ErrorMessageString := 'File not open for output';
  940.   end;
  941.   case TheOpCode of
  942.     EOC_CHANGEDIR : OperationString := 'Unable to Change Directory due to ';
  943.     EOC_SOURCECOPY : OperationString := 'Unable to Copy due to Source File ';
  944.     EOC_DESTCOPY : OperationString := 'Unable to Copy due to Destination File ';
  945.     EOC_DELETEFILE : OperationString := 'Unable to Delete File due to ';
  946.     EOC_DELETEDIR : OperationString := 'Unable to Delete Directory due to ';
  947.     EOC_RENAMEFILE : OperationString := 'Unable to Rename File due to ';
  948.     EOC_MAKEDIR : OperationString := 'Unable to Create New Directory due to ';
  949.     EOC_SETATTR : OperationString := 'Unable to Set File Attributes due to ';
  950.   end;
  951.   { If not recognized use message; not a DOS error; reset cursor for neatness }
  952.   if ErrorMessageString = '' then
  953.   begin
  954.     Screen.Cursor := crDefault;
  955.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' ' +
  956.      TheMessage , mtError , [mbOK],0);
  957.   end
  958.   else
  959.   begin
  960.     { Recognized DOS exception, reset cursor for neatness }
  961.     Screen.Cursor := crDefault;
  962.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' ' +
  963.      ErrorMessageString , mtError , [mbOK], 0 );
  964.   end;
  965. end;
  966.  
  967. { This procedure handles displaying a user-friendly Dialog box with a }
  968. { Message for DOS error codes.                                        }
  969. procedure TFileWorkBench.HandleDOSError( TheOpCode : Integer;
  970.            ThePath : String;  TheCode : Integer );
  971. var ErrorMessageString : String;  { internal message holder }
  972.     OperationString : String;     { internal message holder }
  973. begin
  974.   { clear the message holder to check for unrecognized code }
  975.   ErrorMessageString := '';
  976.   { Negate the code back to normal number and check to set string }
  977.   case -TheCode of
  978.     2    : ErrorMessageString := 'File not found';
  979.     3    : ErrorMessageString := 'Path not found';
  980.     4    : ErrorMessageString := 'Too many open files';
  981.     5    : ErrorMessageString := 'File access denied';
  982.     6    : ErrorMessageString := 'Invalid file handle';
  983.     12    : ErrorMessageString := 'Invalid file access code';
  984.     15    : ErrorMessageString := 'Invalid drive number';
  985.     16  : ErrorMessageString := 'Cannot remove current directory';
  986.     17    : ErrorMessageString := 'Cannot rename across drives';
  987.     100    : ErrorMessageString := 'Disk read error';
  988.     101    : ErrorMessageString := 'Disk write error';
  989.     102    : ErrorMessageString := 'File not assigned';
  990.     103    : ErrorMessageString := 'File not open';
  991.     104    : ErrorMessageString := 'File not open for input';
  992.     105    : ErrorMessageString := 'File not open for output';
  993.     157 : ErrormessageString := 'Could not open Source File';
  994.     159 : ErrormessageString := 'Could not open Target File';
  995.   end;
  996.   case TheOpCode of
  997.     EOC_CHANGEDIR : OperationString := 'Unable to Change Directory due to ';
  998.     EOC_SOURCECOPY : OperationString := 'Unable to Copy due to Source File ';
  999.     EOC_DESTCOPY : OperationString := 'Unable to Copy due to Destination File ';
  1000.     EOC_DELETEFILE : OperationString := 'Unable to Delete File due to ';
  1001.     EOC_DELETEDIR : OperationString := 'Unable to Delete Directory due to ';
  1002.     EOC_RENAMEFILE : OperationString := 'Unable to Rename File due to ';
  1003.     EOC_MAKEDIR : OperationString := 'Unable to Create New Directory due to ';
  1004.     EOC_SETATTR : OperationString := 'Unable to Set File Attributes due to ';
  1005.   end;
  1006.   { If the string is empty an unrecognized code was sent in }
  1007.   if ErrorMessageString = '' then
  1008.   begin
  1009.     { Sent up db based on source or target error; reset cursor for neatness }
  1010.     Screen.Cursor := crDefault;
  1011.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' Error Code: ' +
  1012.      IntToStr( TheCode ) , mtError , [mbOK],0);
  1013.   end
  1014.   else  { Code is recognized, use message from case statement }
  1015.   begin
  1016.     { Format the output for source or target error }
  1017.     Screen.Cursor := crDefault;
  1018.     MessageDlg( OperationString + ExtractFileName( ThePath ) + ' ' +
  1019.      ErrorMessageString , mtError , [mbOK], 0 );
  1020.   end;
  1021. end;
  1022.  
  1023. { This procedure sets the imported booleans to the file's attributes }
  1024. procedure TFileWorkBench.GetFileAttributes( TheFile : String; var IsDirectory ,
  1025.            IsArchive , IsVolumeID , IsHidden , IsReadOnly ,
  1026.             IsSysFile : Boolean );
  1027. var TheResult : Integer; { Traps for error code on VolumeID }
  1028. begin
  1029.   { Clear the imported flags for default }
  1030.   IsDirectory := false;
  1031.   IsArchive := false;
  1032.   IsVolumeID := false;
  1033.   IsHidden := False;
  1034.   IsReadOnly := false;
  1035.   IsSysFile := false;
  1036.   { Make the Dos call }
  1037.   TheResult := FileGetAttr( TheFile );
  1038.   if TheResult < 0 then
  1039.   begin
  1040.     { Volume ID returns -2 (?) }
  1041.     IsVolumeID := true;
  1042.     { It has no other properties }
  1043.     exit;
  1044.   end;
  1045.   { Use AND test to set all other properties }
  1046.   if (( TheResult and faDirectory ) = faDirectory ) then IsDirectory := true;
  1047.   if (( TheResult and faArchive ) = faArchive ) then IsArchive := true;
  1048.   if (( TheResult and faVolumeID ) = faVolumeID ) then IsVolumeID := true;
  1049.   if (( TheResult and faReadOnly ) = faReadOnly ) then IsReadOnly := true;
  1050.   if (( TheResult and faHidden ) = faHidden ) then IsHidden := true;
  1051.   if (( TheResult and faSysFile ) = faSysFile ) then IsSysFile := true;
  1052. end;
  1053.  
  1054. { This function makes sure a pathname has a trailing \ }
  1055. function TFileWorkBench.ForceTrailingBackSlash(
  1056.           const TheFileName : String ) : String;
  1057. var TempString : String;  { Used to hold function result }
  1058. begin
  1059.   { If no trailing \ add one (root will already have one.) }
  1060.   if TheFileName[ Length( TheFileName ) ] <> '\' then
  1061.    TempString := TheFileName + '\' else TempString := TheFileName;
  1062.   { Return modified or non-modified string }
  1063.   ForceTrailingBackslash := TempString;
  1064. end;
  1065.  
  1066. { This function makes sure a non-root dir has no trailing \ }
  1067. function TFileWorkBench.StripNonRootTrailingBackSlash(
  1068.           const TheFileName : String ) : String;
  1069. var TempString : String ; { Used to hold function result }
  1070. begin
  1071.   { Default is no change }
  1072.   TempString := TheFileName;
  1073.   { If not root then }
  1074.   if Length( TheFileName ) > 3 then
  1075.   begin
  1076.     { If has a trailing backslash remove it }
  1077.     if TheFileName[ Length( TheFileName )] = '\' then
  1078.     begin
  1079.       TempString := Copy( TheFileName , 1 ,
  1080.        Length( TheFileName ) - 1 );
  1081.     end;
  1082.   end;
  1083.   { Export the final result }
  1084.   StripNonRootTrailingBackSlash := TempString;
  1085. end;
  1086.  
  1087. { This gets the next selected listbox item }
  1088. function TIconFileListBox.GetNextSelection( SourceDirectory : String;
  1089.           var CurrentItem : Integer ): String;
  1090. var TheResult : String;  { Internal storage }
  1091.     finished  : boolean; { Loop flag        }
  1092. begin
  1093.   { If out of items to check signal and exit }
  1094.   if CurrentItem > Items.Count then TheResult := '' else
  1095.   begin
  1096.     { Otherwise scan from current position till match or end }
  1097.     finished := false;
  1098.     while not finished do
  1099.     begin
  1100.       { Check against selected property }
  1101.       if Selected[ CurrentItem - 1 ] then
  1102.       begin
  1103.         { If selected then return it and abort loop }
  1104.         TheResult := SourceDirectory + Items[ CurrentItem - 1 ];
  1105.         finished := true;
  1106.         { Increment current position }
  1107.         CurrentItem := CurrentItem + 1;
  1108.      end
  1109.       else
  1110.       begin
  1111.         { Increment current position }
  1112.         CurrentItem := CurrentItem + 1;
  1113.         { Otherwise check for end of data and abort if out of entries }
  1114.         if CurrentItem > Items.Count then
  1115.         begin
  1116.           TheResult := '';
  1117.           finished := true;
  1118.         end;
  1119.       end;
  1120.     end;
  1121.   end;
  1122.   { Return stored result }
  1123.   GetNextSelection := TheResult;
  1124. end;
  1125.  
  1126. { Modified from VCL Source Copyright 1995 }
  1127. { Borland International, Inc.             }
  1128. { Use this to override display with icons }
  1129. procedure TIconFileListBox.ReadFileNames;
  1130. var
  1131.   AttrIndex   : TFileAttr;
  1132.   i           : Integer;
  1133.   FileExt     : string;
  1134.   MaskPtr     : PChar;
  1135.   Ptr         : PChar;
  1136.   AttrWord    : Word;
  1137.   TempPicture : TPicture;
  1138.   TempBmp     : TBitmap;
  1139.   TempIcon    : TIcon;
  1140. const
  1141.   Attributes: array[TFileAttr] of Word =
  1142.   ( DDL_READONLY , DDL_HIDDEN , DDL_SYSTEM , $0008 , DDL_DIRECTORY ,
  1143.     DDL_ARCHIVE  , DDL_EXCLUSIVE );
  1144. begin
  1145.   { if no handle allocated yet, this call will force         }
  1146.   { one to be allocated incorrectly (i.e. at the wrong time. }
  1147.   { In due time, one will be allocated appropriately.        }
  1148.   AttrWord := DDL_READWRITE;
  1149.   if HandleAllocated then
  1150.   begin
  1151.     { Set attribute flags based on values in FileType }
  1152.     for AttrIndex := ftReadOnly to ftArchive do
  1153.      if AttrIndex in FileType then
  1154.       AttrWord := AttrWord or Attributes[ AttrIndex ];
  1155.  
  1156.     { Use Exclusive bit to exclude normal files }
  1157.     if not ( ftNormal in FileType ) then
  1158.       AttrWord := AttrWord or DDL_EXCLUSIVE;
  1159.  
  1160.     ChDir( FDirectory ); { go to the directory we want }
  1161.     Clear;               { clear the list }
  1162.  
  1163.     MaskPtr := FMask;
  1164.     while MaskPtr <> nil do
  1165.     begin
  1166.       Ptr := StrScan ( MaskPtr , ';' );
  1167.       if Ptr <> nil then  Ptr^ := #0;
  1168.       { build the list }
  1169.       SendMessage( Handle , LB_DIR , AttrWord , Longint( MaskPtr ));
  1170.       if Ptr <> nil then
  1171.       begin
  1172.         Ptr^ := ';';
  1173.         Inc ( Ptr );
  1174.       end;
  1175.       MaskPtr := Ptr;
  1176.     end;
  1177.     { Now add the bitmaps }
  1178.     {---------------------------- begin custom code --------------------------}
  1179.     { Create the TPicture for exchange purposes }
  1180.     TempPicture := TPicture.Create;
  1181.     { Set it to icon widths }
  1182.     TempPicture.Bitmap.Width := 32;
  1183.     TempPicture.Bitmap.Height := 32;
  1184.     { Run down the list }
  1185.     for i := 0 to Items.Count - 1 do
  1186.     begin
  1187.       { Create a new temporary icon }
  1188.       TempIcon := TIcon.Create;
  1189.       { Call the custom DRWS routine to get icon for a file }
  1190.       GetIconForFile( Items[ i ] , TempIcon );
  1191.       { Put the icon on the bitmap for the picture via draw }
  1192.       { Note 1 , 1 due to bug in Draw?                      }
  1193.       TempPicture.Bitmap.Canvas.Draw( 1 , 1 , TempIcon );
  1194.       { Create a temporary bitmap }
  1195.       TempBmp := TBitmap.Create;
  1196.       { Set its width to those of the previous object's bitmaps }
  1197.       TempBmp.Width := 16;
  1198.       TempBmp.Height := 15;
  1199.       { Resize the icon's bitmap to the smaller size with stretchdraw }
  1200.       TempBmp.Canvas.StretchDraw( Rect( 1 , 1 , 15 , 14 ) ,
  1201.        TempPicture.Bitmap );
  1202.       { Set the Objects list to the bitmap }
  1203.       Items.Objects[ i ] := TempBmp;
  1204.       { Free the icon each iteration; don't free the TempBmp as list does }
  1205.       TempIcon.Free;
  1206.     end;
  1207.     { Free the TPicture exchange element }
  1208.     TempPicture.Free;
  1209.     {------------------------ end custom code --------------------------------}
  1210.     Change;
  1211.   end;
  1212. end;
  1213.  
  1214. { Use this to respond to dbl-clicking FLB filename }
  1215. procedure TIconFileListBox.TheDblClick(Sender: TObject);
  1216. begin
  1217.   { Call shellexec as a wrapper around ShellExecute API call }
  1218.   { False indicates failure, signal error                    }
  1219.   if not ShellExec( ExpandFileName( Items[ ItemIndex ] ), '' , '', false ,
  1220.    SW_SHOWNORMAL , false ) then MessageDlg('Could not Shell out to ' +
  1221.     Items[ ItemIndex ] , mtError, [mbOK], 0);
  1222. end;
  1223.  
  1224. { Create method for FIP                                }
  1225. constructor TIconFileListBox.Create( AOwner : TComponent );
  1226. begin
  1227.   { call inherited -- VITAL! }
  1228.   inherited Create( AOwner );
  1229.   { set the mouse method }
  1230.   OnDblClick := TheDblClick;
  1231. end;
  1232.  
  1233. { Create method for FIP                                }
  1234. constructor TFileIconPanel.Create( AOwner : TComponent );
  1235. begin
  1236.   { call inherited -- VITAL! }
  1237.   inherited Create( AOwner );
  1238.   { create icon and label components, making self owner/displayer }
  1239.   FTheIcon := TIcon.Create;
  1240.   FTheLabel := TLabel.Create( Self );
  1241.   FThelabel.Parent := Self;
  1242.   { Set own and labels mouse methods to stored methods }
  1243.   OnMouseUp := TheMouseUp;
  1244.   OnMouseDown := TheMouseDown;
  1245.   OnDragOver := TheDragOver;
  1246.   OnDragDrop := TheDragDrop;
  1247.   { Set alignment and autosize properties of the label }
  1248.   FTheLabel.Autosize := false;
  1249.   FTheLabel.Alignment := taCenter;
  1250.   { Set selected to false }
  1251.   Selected := false;
  1252. end;
  1253.  
  1254. procedure TFileIconPanel.WMLButtonDblClk(var Message: TWMLButtonDblClk);
  1255. var CurrentDirectory : String;    { Use to store dirs }
  1256.     TheDrive         : String;    { Get drive letter  }
  1257.     WhichDrive       : Integer;   { Get drive number  }
  1258.     ErrorCheck       : Integer;
  1259.     TheFWB           : TFileWorkBench;
  1260. begin
  1261.   { Create FileWorkBench for later use }
  1262.   TheFWB := TFileWorkBench.Create( Self );
  1263.   { Check for label or FIP sender }
  1264.   if FTheLabel.Caption = '..' then
  1265.   begin { deal with backup request }
  1266.     { Change to new directory }
  1267.     TheFWB.ChangeTheDirectory( '..' );
  1268.     { Call special method due to SendMessage problem! }
  1269.     TFileIconPanelScrollBox( Parent ).Update;
  1270.   end
  1271.   else
  1272.   begin
  1273.     { Check for DRIVE id in name }
  1274.     if Pos( 'DRIVE' , FTheName ) <> 0 then
  1275.     begin { Double Click on a Drive Icon }
  1276.       { Pull out the letter from name }
  1277.       TheDrive := Copy( FtheName , 7 , 1 );
  1278.       { Convert it to a number }
  1279.       WhichDrive := ( Ord( TheDrive[ 1 ] ) - Ord( 'A' )) + 1;
  1280.       TheFWB.ChangeTheDriveAndDirectory( WhichDrive );
  1281.       { Call special method due to SendMessage problem! }
  1282.       TFileIconPanelScrollBox( Parent ).Update;
  1283.     end
  1284.     else
  1285.     begin { Double click on a dir/file icon }
  1286.       if (( FileGetAttr( FTheName ) and faDirectory ) = faDirectory ) then
  1287.       begin { A directory, change to it }
  1288.         { Since full path in name, simply change to it! }
  1289.         TheFWB.ChangeTheDirectory( FTheName );
  1290.         { Call special method due to SendMessage problem! }
  1291.         TFileIconPanelScrollBox( Parent ).Update;
  1292.       end
  1293.       else
  1294.       begin { A file; attempt to shellexecute it }
  1295.         { Call shellexec as a wrapper around ShellExecute API call }
  1296.         { False indicates failure, signal error                    }
  1297.         if not ShellExec( FTheName , '' , '', false , SW_SHOWNORMAL , false )
  1298.          then MessageDlg('Could not Shell out to ' + FTheName , mtError,
  1299.           [mbOK], 0);
  1300.       end;
  1301.     end;
  1302.   end;
  1303.   TheFWB.Free; { This prevents resource leak }
  1304. end;
  1305.  
  1306. { Initialization method for FIP                                         }
  1307. procedure TFileIconPanel.Initialize( PanelX              ,
  1308.                                      PanelY              ,
  1309.                                      PanelWidth          ,
  1310.                                      PanelHeight         ,
  1311.                                      PanelBevelWidth     ,
  1312.                                      LabelFontSize         : Integer;
  1313.                                      PanelColor          ,
  1314.                                      PanelHighlightColor ,
  1315.                                      PanelShadowColor    ,
  1316.                                      LabelTextColor        : TColor;
  1317.                                      TheFilename         ,
  1318.                                      LabelFontName         : String;
  1319.                                      LabelFontStyle        : TFontStyles;
  1320.                                      ExtraData             : Integer );
  1321.  
  1322. var TheLabelHeight ,             { Holder for label pixel height }
  1323.     TheLabelWidth    : Integer;  { Holder for label pixel width  }
  1324.     TheOtherPChar    : PChar;    { Windows ASCIIZ string         }
  1325. begin
  1326.   { Set the basic properties based on imported parameters }
  1327.   Left := PanelX;
  1328.   Top := PanelY;
  1329.   Width := PanelWidth;
  1330.   Height := PanelHeight;
  1331.   Color := PanelColor;
  1332.   BevelWidth := PanelBevelWidth;
  1333.   FHighlightColor := PanelHighlightColor;
  1334.   FShadowColor := PanelShadowColor;
  1335.   FTheName := TheFilename;
  1336.   { If the ExtraData field is non-0 then a drive is being sent in }
  1337.   if ExtraData <> 0 then
  1338.   begin
  1339.     { Use the data field value to determine which icon to get from RES file }
  1340.     case ExtraData of
  1341.       1 : begin
  1342.             GetMem( TheOtherPChar , 255 );
  1343.             StrPCopy( TheOtherPChar , 'FLOPPY35' );
  1344.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  1345.             FreeMem( TheOtherPChar , 255 );
  1346.           end;
  1347.       2 : begin
  1348.             GetMem( TheOtherPChar , 255 );
  1349.             StrPCopy( TheOtherPChar , 'FIXEDHD' );
  1350.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  1351.             FreeMem( TheOtherPChar , 255 );
  1352.           end;
  1353.       3 : begin
  1354.             GetMem( TheOtherPChar , 255 );
  1355.             StrPCopy( TheOtherPChar , 'NETWORKHD' );
  1356.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  1357.             FreeMem( TheOtherPChar , 255 );
  1358.           end;
  1359.       4 : begin
  1360.             GetMem( TheOtherPChar , 255 );
  1361.             StrPCopy( TheOtherPChar , 'CDROM' );
  1362.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  1363.             FreeMem( TheOtherPChar , 255 );
  1364.           end;
  1365.       5 : begin
  1366.             GetMem( TheOtherPChar , 255 );
  1367.             StrPCopy( TheOtherPChar , 'RAM' );
  1368.             FTheIcon.Handle := LoadIcon( hInstance , TheOtherPChar );
  1369.             FreeMem( TheOtherPChar , 255 );
  1370.           end;
  1371.     end;
  1372.     { The FileNme property is already set up for the caption; use directly }
  1373.     FTheLabel.Caption := TheFilename;
  1374.     { Set up the hint for later use (make sure to set ShowHint) }
  1375.     Hint := 'Change to ' + TheFileName;
  1376.     ShowHint := true;
  1377.     { Set up all imported label properties and center it for drawing }
  1378.     with FTheLabel do
  1379.     begin
  1380.       Font.Name := LabelFontName;
  1381.       Font.Size := LabelFontSize;
  1382.       Font.Style := LabelFontStyle;
  1383.       Font.Color := LabelTextColor;
  1384.       Canvas.Brush.Color := PanelColor;
  1385.       Canvas.Font := Font;
  1386.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  1387.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  1388.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  1389.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  1390.       Top := Top + Round( Self.Height * 0.75 );
  1391.       Height := TheLabelHeight;
  1392.       Width := TheLabelWidth;
  1393.     end;
  1394.   end
  1395.   else
  1396.   begin
  1397.     { A file or directory has been sent in; use GetIconForFile to obtain an }
  1398.     { icon either from the file, its owner, or a RES file default.          }
  1399.     GetIconForFile( FTheName , FTheIcon );
  1400.     { Check for the Backup caption and set it specially }
  1401.     if ExtractfileName( FThename ) = '..' then
  1402.     begin
  1403.       FTheLabel.Caption := '..';
  1404.       Hint := 'Up One Level';
  1405.     end
  1406.     else
  1407.     begin
  1408.       { Otherwise just get the filename for the label caption }
  1409.       { And the full path for the hint (used later.)          }
  1410.       FTheLabel.caption := ExtractFileName( UpperCase( FTheName ));
  1411.       Hint := FTheName;
  1412.     end;
  1413.     { Activate showhint so hints are seen }
  1414.     ShowHint := true;
  1415.     { Set label properties with imported values and center for display }
  1416.     with FTheLabel do
  1417.     begin
  1418.       Font.Name := LabelFontName;
  1419.       Font.Size := LabelFontSize;
  1420.       Font.Style := LabelFontStyle;
  1421.       Font.Color := LabelTextColor;
  1422.       Canvas.Brush.Color := PanelColor;
  1423.       Canvas.Font := Font;
  1424.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  1425.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  1426.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  1427.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  1428.       Top := Top + Round( Self.Height * 0.75 );
  1429.       Height := TheLabelHeight;
  1430.       Width := TheLabelWidth;
  1431.     end;
  1432.   end;
  1433. end;
  1434.  
  1435. { Destroy method for FIP }
  1436. destructor TFileIconPanel.Destroy;
  1437. begin
  1438.   { free component resources }
  1439.   FTheIcon.Free;
  1440.   FTheLabel.Free;
  1441.   { call inherited -- VITAL! }
  1442.   inherited Destroy;
  1443. end;
  1444.  
  1445. { Mousedown method for FIP; used to allow dragging }
  1446. procedure TFileIconPanel.TheMouseDown(Sender: TObject;
  1447.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1448. begin
  1449.   { Begin a conditional drag operation (false allows timer) }
  1450.   TheIOManager.WhichButton := Button;
  1451.   TheIOManager.WhichState := Shift;
  1452.   BeginDrag( false );
  1453.   { Currently ignore drive clicks }
  1454.   if Pos( 'DRIVE' , FTheName ) > 0 then exit;
  1455.   { Flip status of bevels }
  1456.   if BevelOuter = bvRaised then BevelOuter := bvLowered else
  1457.    BevelOuter := bvRaised;
  1458.   { Flip selected variable }
  1459.   Selected := not Selected;
  1460.   { Set redisplay }
  1461. end;
  1462.  
  1463. { Mouseup Method for FIP; used to allow dragging }
  1464. procedure TFileIconPanel.TheMouseUp(Sender: TObject;
  1465.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  1466. begin
  1467.   { End a drag operation without dropping; if dragged OK }
  1468.   { already handled.                                     }
  1469.   EndDrag( false );
  1470.   { If the right button is clicked, perform magic! }
  1471.   if Button = mbRight then
  1472.    TCCFileMgrForm( TFileIconPanelScrollbox( Parent ).
  1473.     TheParentForm ).BitBtn6Click( Self );
  1474.   { Redisplay on general principles }
  1475.   Invalidate;
  1476. end;
  1477.  
  1478. { Use this to generically OK DnD from FIPs }
  1479. procedure TFileIconPanel.TheDragOver(Sender, Source: TObject; X,
  1480.   Y: Integer; State: TDragState; var Accept: Boolean);
  1481. begin
  1482.   { Only accept from FileIconPanel components }
  1483.   if Source is TFileIconPanel then Accept := true else Accept := false;
  1484. end;
  1485.  
  1486. { Use this to accept Drag and Drop from other FIPs }
  1487. procedure TFileIconPanel.TheDragDrop(Sender, Source: TObject; X,
  1488.   Y: Integer);
  1489. var CurrentName ,                 { Holds work name}
  1490.     TheOldString : String;        { Holds Dir      }
  1491.     TargetDir    : String;        { target of op   }
  1492.     TheResult       : Integer;    { Modal res hold }
  1493.     SourceDirectory,
  1494.     TargetDirectory,
  1495.     CurrentDirectory : String;    { Use to store dirs }
  1496.     TheDrive         : String;    { Get drive letter  }
  1497.     WhichDrive       : Integer;   { Get drive number  }
  1498.     ErrorCheck       : Integer;
  1499.     TheFWB           : TFileWorkBench;
  1500.     ThePosition : Integer;
  1501.     Finished : Boolean;
  1502.     TheFIPSB : TFileIconPanelScrollBox;
  1503. begin
  1504.   { If drop target is .. then ignore }
  1505.   if FTheLabel.Caption = '..' then exit;
  1506.   { Likewise ignore Dnd from drive icons }
  1507.   if Pos( 'DRIVE' , TFileIconPanel( Source ).FtheName ) > 0 then exit;
  1508.   { Obtain the parent of the source FIP; may not be self }
  1509.   TheFIPSB := TFileIconPanelScrollBox( TFileIconPanel( Source ).Parent );
  1510.   { Obtain source directory either as Dir or filepath }
  1511.   if (( FileGetAttr( TFileIconPanel( Source ).FTheName )
  1512.    and faDirectory ) = faDirectory ) then
  1513.   begin  { Directory; take whole path }
  1514.     SourceDirectory := TFileIconPanel( Source ).FTheName;
  1515.   end
  1516.   else
  1517.   begin { File; get pathname }
  1518.     SourceDirectory := ExtractFilePath( TFileIconPanel( Source ).FTheName );
  1519.   end;
  1520.   Sourcedirectory := TheFIPSB.TheFWB.ForceTrailingBackSlash( SourceDirectory );
  1521.   if Pos( 'DRIVE' , FTheName ) > 0 then
  1522.   begin { Drop onto a drive icon; perform action to its default dir }
  1523.     { Pull out the letter from name }
  1524.     TheDrive := Copy( FtheName , 7 , 1 );
  1525.     { Convert it to a number }
  1526.     WhichDrive := ( Ord( TheDrive[ 1 ] ) - Ord( 'A' )) + 1;
  1527.     { Determine the target directory and drive }
  1528.     GetDir( WhichDrive , TargetDirectory );
  1529.     TargetDirectory := TheFIPSB.TheFWB.ForceTrailingbackSlash( TargetDirectory );
  1530.     { Check for shift to operate on all selections }
  1531.     if TheIOManager.WasSHIFTPressed then
  1532.     begin { Operate on all selections }
  1533.       { Obtain the parent directory of the FIP dragged over }
  1534.       SourceDirectory := ExtractFilePath( TFileIconPanel( Source ).FTheName );
  1535.       SourceDirectory := TheFIPSB.TheFWB.ForceTrailingBackslash( SourceDirectory );
  1536.       { If SourceDir subset of TargetDir then abort; recursive failure }
  1537.       if Pos( SourceDirectory , TargetDirectory ) > 0 then
  1538.       begin
  1539.         MessageDlg( 'Cannot drag to same directory!',mtError,[mbOK],0 );
  1540.         exit;
  1541.       end;
  1542.       if TargetDirectory[ 1 ] <> SourceDirectory[ 1 ] then
  1543.       begin { Copy to different drives }
  1544.         if TheIOManager.WasALTPressed then
  1545.         begin { ALT overrides and does move }
  1546.           { Set up to get all current selections }
  1547.           ThePosition := 1;
  1548.           finished := false;
  1549.           while not finished do
  1550.           begin
  1551.             CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1552.                    ThePosition );
  1553.             { If returns blank string then out of selections }
  1554.             if CurrentName = '' then finished := true else
  1555.             begin
  1556.               { If a directory signal error }
  1557.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1558.               begin
  1559.                 if MessageDlg( 'Move Directory ' + CurrentName + ' to ' +
  1560.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1561.                   TheFIPSB.TheFWB.RecursivelyMoveDirectory( CurrentName ,
  1562.                    TargetDirectory );
  1563.               end
  1564.               else
  1565.               begin
  1566.                 TheFIPSB.TheFWB.MoveTheFile( CurrentName , TargetDirectory );
  1567.               end;
  1568.             end;
  1569.             { Reset to normal cursor }
  1570.             Screen.Cursor := crDefault;
  1571.           end;
  1572.         end
  1573.         else
  1574.         begin { Default is to do copy like file manager }
  1575.           { Set up to get all current selections }
  1576.           ThePosition := 1;
  1577.           finished := false;
  1578.           while not finished do
  1579.           begin
  1580.              CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1581.                    ThePosition );
  1582.             { If returns blank string then out of selections }
  1583.             if CurrentName = '' then finished := true else
  1584.             begin
  1585.               { If a directory signal error }
  1586.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1587.               begin
  1588.                 if MessageDlg( 'Copy Directory ' + CurrentName + ' to ' +
  1589.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1590.                   TheFIPSB.TheFWB.RecursivelyCopyDirectory( CurrentName ,
  1591.                    TargetDirectory );
  1592.               end
  1593.               else
  1594.               begin
  1595.                 TheFIPSB.TheFWB.CopyTheFile( CurrentName , TargetDirectory );
  1596.               end;
  1597.             end;
  1598.             { Reset to normal cursor }
  1599.             Screen.Cursor := crDefault;
  1600.           end;
  1601.         end;
  1602.       end
  1603.       else
  1604.       begin { Copy to same drive }
  1605.         if TheIOManager.WasCTRLPressed then
  1606.         begin { CTRL overrides and does copy }
  1607.           { Set up to get all current selections }
  1608.           ThePosition := 1;
  1609.           finished := false;
  1610.           while not finished do
  1611.           begin
  1612.             CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1613.                    ThePosition );
  1614.             { If returns blank string then out of selections }
  1615.             if CurrentName = '' then finished := true else
  1616.             begin
  1617.               { If a directory signal error }
  1618.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1619.               begin
  1620.                 if MessageDlg( 'Copy Directory ' + CurrentName + ' to ' +
  1621.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1622.                   TheFIPSB.TheFWB.RecursivelyCopyDirectory( CurrentName ,
  1623.                    TargetDirectory );
  1624.               end
  1625.               else
  1626.               begin
  1627.                 TheFIPSB.TheFWB.CopyTheFile( CurrentName , TargetDirectory );
  1628.               end;
  1629.             end;
  1630.             { Reset to normal cursor }
  1631.             Screen.Cursor := crDefault;
  1632.           end;
  1633.         end
  1634.         else
  1635.         begin { Default is to do move like file manager }
  1636.           { Set up to get all current selections }
  1637.           ThePosition := 1;
  1638.           finished := false;
  1639.           while not finished do
  1640.           begin
  1641.             CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1642.                    ThePosition );
  1643.             { If returns blank string then out of selections }
  1644.             if CurrentName = '' then finished := true else
  1645.             begin
  1646.               { If a directory signal error }
  1647.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1648.               begin
  1649.                 if MessageDlg( 'Move Directory ' + CurrentName + ' to ' +
  1650.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1651.                   TheFIPSB.TheFWB.RecursivelyMoveDirectory( CurrentName ,
  1652.                    TargetDirectory );
  1653.               end
  1654.               else
  1655.               begin
  1656.                 TheFIPSB.TheFWB.MoveTheFile( CurrentName , TargetDirectory );
  1657.               end;
  1658.             end;
  1659.             { Reset to normal cursor }
  1660.             Screen.Cursor := crDefault;
  1661.           end;
  1662.         end;
  1663.       end;
  1664.     end
  1665.     else
  1666.     begin { Operate on only source }
  1667.       if TargetDirectory[ 1 ] <> SourceDirectory[ 1 ] then
  1668.       begin { Copy to different drives }
  1669.         if TheIOManager.WasALTPressed then
  1670.         begin { ALT overrides and does move }
  1671.           with Source as TFileIconPanel do
  1672.           begin
  1673.             if MessageDlg( 'Move ' + FTheName + ' to ' +
  1674.              TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1675.               TheFIPSB.TheFWB.MoveTheFile( FTheName , TargetDirectory );
  1676.           end;
  1677.         end
  1678.         else
  1679.         begin { Default is to do copy like file manager }
  1680.           with Source as TFileIconPanel do
  1681.           begin
  1682.             if MessageDlg( 'Copy ' + FTheName + ' to ' +
  1683.              TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1684.               TheFIPSB.TheFWB.CopyTheFile( FtheName , TargetDirectory );
  1685.           end;
  1686.         end;
  1687.       end
  1688.       else
  1689.       begin { Copy to same drive }
  1690.         if TheIOManager.WasCTRLPressed then
  1691.         begin { CTRL overrides and does copy }
  1692.           with Source as TFileIconPanel do
  1693.           begin
  1694.             if MessageDlg( 'Copy ' + FTheName + ' to ' +
  1695.              TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1696.               TheFIPSB.TheFWB.CopyTheFile( FTheName , TargetDirectory );
  1697.           end;
  1698.         end
  1699.         else
  1700.         begin { Default is to do move like file manager }
  1701.           with Source as TFileIconPanel do
  1702.           begin
  1703.             if MessageDlg( 'Move ' + FTheName + ' to ' +
  1704.              TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1705.              TheFIPSB.TheFWB.MoveTheFile( FtheName , TargetDirectory );
  1706.           end;
  1707.         end;
  1708.       end;
  1709.     end;
  1710.   end
  1711.   else
  1712.   begin { Drop onto dir or file icon }
  1713.     if (( FileGetAttr( FTheName ) and faDirectory ) = faDirectory ) then
  1714.     begin { Drop onto a directory; use its path as target }
  1715.       TargetDirectory := FTheName;
  1716.     end
  1717.     else
  1718.     begin { Drop onto a file; use its parent as target }
  1719.       TargetDirectory := ExtractFilePath( FTheName );
  1720.     end;
  1721.     Targetdirectory := TheFIPSB.TheFWB.ForceTrailingbackslash( TargetDirectory );
  1722.     { Check for shift to operate on all selections }
  1723.     if TheIOManager.WasSHIFTPressed then
  1724.     begin { Operate on all selections }
  1725.       { Obtain the parent directory of the FIP dragged over }
  1726.       SourceDirectory := ExtractFilePath( TFileIconPanel( Source ).FTheName );
  1727.       SourceDirectory := TheFIPSB.TheFWB.ForceTrailingBackslash( SourceDirectory );
  1728.       { If SourceDir subset of TargetDir then abort; recursive failure }
  1729.       if Pos( SourceDirectory , TargetDirectory ) > 0 then
  1730.       begin
  1731.         MessageDlg( 'Cannot drag to same directory!',mtError,[mbOK],0 );
  1732.         exit;
  1733.       end;
  1734.       if TargetDirectory[ 1 ] <> SourceDirectory[ 1 ] then
  1735.       begin { Copy to different drives }
  1736.         if TheIOManager.WasALTPressed then
  1737.         begin { ALT overrides and does move }
  1738.           { Set up to get all current selections }
  1739.           ThePosition := 1;
  1740.           finished := false;
  1741.           while not finished do
  1742.           begin
  1743.              CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1744.                    ThePosition );
  1745.             { If returns blank string then out of selections }
  1746.             if CurrentName = '' then finished := true else
  1747.             begin
  1748.               { If a directory signal error }
  1749.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1750.               begin
  1751.                 if MessageDlg( 'Move Directory ' + CurrentName + ' to ' +
  1752.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1753.                   TheFIPSB.TheFWB.RecursivelyMoveDirectory( CurrentName ,
  1754.                    TargetDirectory );
  1755.               end
  1756.               else
  1757.               begin
  1758.                 TheFIPSB.TheFWB.MoveTheFile( CurrentName , TargetDirectory );
  1759.               end;
  1760.             end;
  1761.             { Reset to normal cursor }
  1762.             Screen.Cursor := crDefault;
  1763.           end;
  1764.         end
  1765.         else
  1766.         begin { Default is to do copy like file manager }
  1767.           { Set up to get all current selections }
  1768.           ThePosition := 1;
  1769.           finished := false;
  1770.           while not finished do
  1771.           begin
  1772.             CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1773.                    ThePosition );
  1774.             { If returns blank string then out of selections }
  1775.             if CurrentName = '' then finished := true else
  1776.             begin
  1777.               { If a directory signal error }
  1778.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1779.               begin
  1780.                 if MessageDlg( 'Copy Directory ' + CurrentName + ' to ' +
  1781.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1782.                   TheFIPSB.TheFWB.RecursivelyCopyDirectory( CurrentName ,
  1783.                    TargetDirectory );
  1784.               end
  1785.               else
  1786.               begin
  1787.                 TheFIPSB.TheFWB.CopyTheFile( CurrentName , TargetDirectory );
  1788.               end;
  1789.             end;
  1790.             { Reset to normal cursor }
  1791.             Screen.Cursor := crDefault;
  1792.           end;
  1793.         end;
  1794.       end
  1795.       else
  1796.       begin { Copy to same drive }
  1797.         if TheIOManager.WasCTRLPressed then
  1798.         begin { CTRL overrides and does copy }
  1799.           { Set up to get all current selections }
  1800.           ThePosition := 1;
  1801.           finished := false;
  1802.           while not finished do
  1803.           begin
  1804.             { Call generic file getting routine based on current view}
  1805.              CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1806.                    ThePosition );
  1807.             { If returns blank string then out of selections }
  1808.             if CurrentName = '' then finished := true else
  1809.             begin
  1810.               { If a directory signal error }
  1811.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1812.               begin
  1813.                 if MessageDlg( 'Copy Directory ' + CurrentName + ' to ' +
  1814.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1815.                   TheFIPSB.TheFWB.RecursivelyCopyDirectory( CurrentName ,
  1816.                    TargetDirectory );
  1817.               end
  1818.               else
  1819.               begin
  1820.                 TheFIPSB.TheFWB.CopyTheFile( CurrentName , TargetDirectory );
  1821.               end;
  1822.             end;
  1823.             { Reset to normal cursor }
  1824.             Screen.Cursor := crDefault;
  1825.           end;
  1826.         end
  1827.         else
  1828.         begin { Default is to do move like file manager }
  1829.           { Set up to get all current selections }
  1830.           ThePosition := 1;
  1831.           finished := false;
  1832.           while not finished do
  1833.           begin
  1834.             { Call generic file getting routine based on current view}
  1835.               CurrentName := TheFIPSB.GetNextSelection( SourceDirectory ,
  1836.                    ThePosition );
  1837.             { If returns blank string then out of selections }
  1838.             if CurrentName = '' then finished := true else
  1839.             begin
  1840.               { If a directory signal error }
  1841.               if (( FileGetAttr( CurrentName ) and faDirectory ) = faDirectory ) then
  1842.               begin
  1843.                 if MessageDlg( 'Move Directory ' + CurrentName + ' to ' +
  1844.                  TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1845.                   TheFIPSB.TheFWB.RecursivelyMoveDirectory( CurrentName ,
  1846.                    TargetDirectory );
  1847.               end
  1848.               else
  1849.               begin
  1850.                 TheFIPSB.TheFWB.MoveTheFile( CurrentName , TargetDirectory );
  1851.               end;
  1852.             end;
  1853.             { Reset to normal cursor }
  1854.             Screen.Cursor := crDefault;
  1855.           end;
  1856.         end;
  1857.       end;
  1858.     end
  1859.     else
  1860.     begin { Operate on only source }
  1861.       if TargetDirectory[ 1 ] <> SourceDirectory[ 1 ] then
  1862.       begin { Copy to different drives }
  1863.         if TheIOManager.WasALTPressed then
  1864.         begin { ALT overrides and does move }
  1865.           with Source as TFileIconPanel do
  1866.           begin
  1867.             if (( FileGetAttr( FTheName ) and faDirectory ) = faDirectory ) then
  1868.             begin
  1869.               if MessageDlg( 'Move Directory ' + FTheName + ' to ' +
  1870.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1871.                 TheFIPSB.TheFWB.RecursivelyMoveDirectory( FtheName ,
  1872.                  TargetDirectory );
  1873.             end
  1874.             else
  1875.             begin
  1876.               if MessageDlg( 'Move ' + FTheName + ' to ' +
  1877.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1878.                 TheFIPSB.TheFWB.MoveTheFile( FTheName , TargetDirectory );
  1879.             end;
  1880.           end;
  1881.         end
  1882.         else
  1883.         begin { Default is to do copy like file manager }
  1884.           with Source as TFileIconPanel do
  1885.           begin
  1886.             if (( FileGetAttr( FTheName ) and faDirectory ) = faDirectory ) then
  1887.             begin
  1888.               if MessageDlg( 'Copy Directory ' + FtheName + ' to ' +
  1889.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1890.                 TheFIPSB.TheFWB.RecursivelyCopyDirectory( FtheName ,
  1891.                  TargetDirectory );
  1892.             end
  1893.             else
  1894.             begin
  1895.               if MessageDlg( 'Copy ' + FTheName + ' to ' +
  1896.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1897.                 TheFIPSB.TheFWB.CopyTheFile( FTheName , TargetDirectory );
  1898.             end;
  1899.           end;
  1900.         end;
  1901.       end
  1902.       else
  1903.       begin { Copy to same drive }
  1904.         if TheIOManager.WasCTRLPressed then
  1905.         begin { CTRL overrides and does copy }
  1906.           with Source as TFileIconPanel do
  1907.           begin
  1908.             if (( FileGetAttr( FTheName ) and faDirectory ) = faDirectory ) then
  1909.             begin
  1910.               if MessageDlg( 'Copy Directory ' + FtheName + ' to ' +
  1911.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1912.                 TheFIPSB.TheFWB.RecursivelyCopyDirectory( FtheName ,
  1913.                  TargetDirectory );
  1914.             end
  1915.             else
  1916.             begin
  1917.               if MessageDlg( 'Copy ' + FTheName + ' to ' +
  1918.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1919.                 TheFIPSB.TheFWB.CopyTheFile( FTheName , TargetDirectory );
  1920.             end;
  1921.           end;
  1922.         end
  1923.         else
  1924.         begin { Default is to do move like file manager }
  1925.           with Source as TFileIconPanel do
  1926.           begin
  1927.             if (( FileGetAttr( FTheName ) and faDirectory ) = faDirectory ) then
  1928.             begin
  1929.               if MessageDlg( 'Move Directory ' + FtheName + ' to ' +
  1930.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1931.                 TheFIPSB.TheFWB.RecursivelyMoveDirectory( FtheName ,
  1932.                  TargetDirectory );
  1933.             end
  1934.             else
  1935.             begin
  1936.               if MessageDlg( 'Move ' + FTheName + ' to ' +
  1937.                TargetDirectory + '?' , mtConfirmation , mbYesNoCancel , 0 ) = mrYes then
  1938.                 TheFIPSB.TheFWB.MoveTheFile( FTheName , TargetDirectory );
  1939.             end;
  1940.           end;
  1941.         end;
  1942.       end;
  1943.     end;
  1944.   end;
  1945.   { Call special method due to SendMessage problem! }
  1946.   TFileIconPanelScrollBox( TFileIconPanel( Source ).Parent ).Update;
  1947.   TFileIconPanelScrollBox( Parent ).Update;
  1948. end;
  1949.  
  1950. { Paint method for FIP; overrides normal paint }
  1951. procedure TFileIconPanel.Paint;
  1952. var
  1953.   TheOtherRect   : TRect;   { Holds clientrect   }
  1954.   TopColor     ,            { Holds bright color }
  1955.   BottomColor    : TColor;  { Holds dark color   }
  1956.  
  1957. { These methods are from Borland Intl., copyright 1995 }
  1958. procedure Frame3D(    Canvas       : TCanvas;
  1959.                   var TheRect      : TRect;
  1960.                       TopColor   ,
  1961.                       BottomColor  : TColor;
  1962.                       Width        : Integer );
  1963.  
  1964. procedure DoRect;
  1965. var
  1966.   TopRight, BottomLeft: TPoint;
  1967. begin
  1968.   with Canvas, TheRect do
  1969.   begin
  1970.     TopRight.X := Right;
  1971.     TopRight.Y := Top;
  1972.     BottomLeft.X := Left;
  1973.     BottomLeft.Y := Bottom;
  1974.     Pen.Color := TopColor;
  1975.     PolyLine([BottomLeft, TopLeft, TopRight]);
  1976.     Pen.Color := BottomColor;
  1977.     Dec(BottomLeft.X);
  1978.     PolyLine([TopRight, BottomRight, BottomLeft]);
  1979.   end;
  1980. end;
  1981.  
  1982. begin
  1983.   Canvas.Pen.Width := 1;
  1984.   Dec(TheRect.Bottom); Dec(TheRect.Right);
  1985.   while Width > 0 do
  1986.   begin
  1987.     Dec(Width);
  1988.     DoRect;
  1989.     InflateRect(TheRect, -1, -1);
  1990.   end;
  1991.   Inc(TheRect.Bottom); Inc(TheRect.Right);
  1992. end;
  1993.  
  1994. procedure AdjustColors(Bevel: TPanelBevel);
  1995. begin
  1996.   TopColor := FHighlightColor;
  1997.   if Bevel = bvLowered then TopColor := FShadowColor;
  1998.   BottomColor := FShadowColor;
  1999.   if Bevel = bvLowered then BottomColor := FHighlightColor;
  2000. end;
  2001.  
  2002. { Custom code begins here }
  2003. begin
  2004.   { Get the rectangle of the control with API/method call }
  2005.   TheOtherRect := GetClientRect;
  2006.   { draw basic rectangle with basic color }
  2007.   with Canvas do
  2008.   begin
  2009.     Brush.Color := Color;
  2010.     FillRect(TheOtherRect);
  2011.   end;
  2012.   { Set up for top "icon" frame  and draw it with frame3d }
  2013.   TheOtherRect.Right := Width;
  2014.   TheOtherRect.Bottom := Round( Height * 0.75 ) - 6 ;
  2015.   if BevelOuter <> bvNone then
  2016.   begin
  2017.     AdjustColors(BevelOuter);
  2018.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  2019.   end;
  2020.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  2021.   if BevelInner <> bvNone then
  2022.   begin
  2023.     AdjustColors(BevelInner);
  2024.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  2025.   end;
  2026.   { Do the same for the lower "label" frame }
  2027.   TheOtherRect.Top := Round( Height * 0.75 ) - 5;
  2028.   TheOtherRect.Left := 0;
  2029.   TheOtherRect.Bottom := Height;
  2030.   TheOtherRect.Right := Width;
  2031.   if BevelOuter <> bvNone then
  2032.   begin
  2033.     AdjustColors(BevelOuter);
  2034.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  2035.   end;
  2036.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  2037.   if BevelInner <> bvNone then
  2038.   begin
  2039.     AdjustColors(BevelInner);
  2040.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  2041.   end;
  2042.   { Then draw the icon using canvas draw method }
  2043.   Canvas.Draw( (( Width - 32 ) div 2 ) + 1 ,
  2044.   ((( Round( Height * 0.75 ) - 6 ) - 32 ) div 2 ) + 1 , FTheIcon );
  2045. end;
  2046.  
  2047. { This procedure clears a scrollbox of all FileIconPanels }
  2048. procedure TFileIconPanelScrollbox.ClearTheFIPs;
  2049. var Counter_1 : Integer;
  2050.     TheComponent : TComponent;
  2051. begin
  2052.   { Note that must use while loop since component count continually }
  2053.   { decreases as removes are made!                                  }
  2054.   while ComponentCount > 0 do
  2055.   begin
  2056.     { Save the component as a generic TComponent }
  2057.     TheComponent := Components[ 0 ];
  2058.     { Call removecomponent to pull it out of the owner list for sb }
  2059.     { This avoids GPF when freeing the sb.                         }
  2060.     RemoveComponent( Components[ 0 ]);
  2061.     if ControlCount > 0 then
  2062.      RemoveControl( Controls[ 0 ] );
  2063.     { Typecast the pointer and free it to release memory and res. }
  2064.     TheParentForm.InsertComponent( TheComponent );
  2065.   end;
  2066. end;
  2067.  
  2068. { This procedure scans for drives and obtains their type and creates file }
  2069. { icon panels to represent them.                                          }
  2070. procedure TFileIconPanelScrollBox.AddDriveIcons( var XCounter ,
  2071.            YCounter : Integer );
  2072. type
  2073.   { This if from filectrl unit; reproduce here for completeness }
  2074.   TDriveType = (dtUnknown, dtNoDrive, dtFloppy, dtFixed, dtNetwork, dtCDROM,
  2075.                 dtRAM);
  2076. var
  2077.   DriveNum        : Integer;         { Used to get next drive via DOS fn   }
  2078.   IconType        : Integer;         { Used to hold icon type (defacto dt) }
  2079.   DriveChar       : Char;            { Used to hold drive letter           }
  2080.   DriveType       : TDriveType;      { Used for set-valued drive type      }
  2081.   Finished        : Boolean;         { Loop flag                           }
  2082.   TheFIP          : TFileIconPanel;  { Generic FileIconPanel variable      }
  2083.   ButtonColor   ,                    { Main panel color                    }
  2084.   ButtonHLColor ,                    { Bright panel color                  }
  2085.   ButtonSColor  ,                    { Dark panel color                    }
  2086.   Textcolor       : TColor;          { Label text color                    }
  2087.  
  2088. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  2089. { Check whether drive is a CD-ROM.  Returns True if MSCDEX is installed }
  2090. {  and the drive is using a CD driver                                   }
  2091.  
  2092. function IsCDROM(DriveNum: Integer): Boolean; assembler;
  2093. asm
  2094.   MOV   AX,1500h { look for MSCDEX }
  2095.   XOR   BX,BX
  2096.   INT   2fh
  2097.   OR    BX,BX
  2098.   JZ    @Finish
  2099.   MOV   AX,150Bh { check for using CD driver }
  2100.   MOV   CX,DriveNum
  2101.   INT   2fh
  2102.   OR    AX,AX
  2103.   @Finish:
  2104. end;
  2105.  
  2106. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  2107. { Check whether drive is a RAM drive.                                   }
  2108. function IsRAMDrive(DriveNum: Integer): Boolean; assembler;
  2109. var
  2110.   TempResult: Boolean;
  2111. asm
  2112.   MOV   TempResult,False
  2113.   PUSH  DS
  2114.   MOV   BX,SS
  2115.   MOV   DS,BX
  2116.   SUB   SP,0200h
  2117.   MOV   BX,SP
  2118.   MOV   AX,DriveNum
  2119.   MOV   CX,1
  2120.   XOR   DX,DX
  2121.   INT   25h  { read boot sector }
  2122.   ADD   SP,2
  2123.   JC    @ItsNot
  2124.   MOV   BX,SP
  2125.   CMP   BYTE PTR SS:[BX+15h],0F8h  { reverify fixed disk }
  2126.   JNE   @ItsNot
  2127.   CMP   BYTE PTR SS:[BX+10h],1  { check for single FAT }
  2128.   JNE   @ItsNot
  2129.   MOV   TempResult,True
  2130.   @ItsNot:
  2131.   ADD   SP,0200h
  2132.   POP   DS
  2133.   MOV   AL, TempResult
  2134. end;
  2135.  
  2136. { This code is from the FileCtrl Unit; copyright Borland Intl 1995      }
  2137. { Finds the type of a drive letter.                                     }
  2138. function FindDriveType(DriveNum: Integer): TDriveType;
  2139. begin
  2140.   Result := TDriveType(GetDriveType(DriveNum));
  2141.   if (Result = dtFixed) or (Result = dtNetwork) then
  2142.   begin
  2143.     if IsCDROM(DriveNum) then Result := dtCDROM
  2144.     else if (Result = dtFixed) then
  2145.     begin
  2146.         { do not check for RAMDrive under Windows NT }
  2147.       if ((GetWinFlags and $4000) = 0) and IsRAMDrive(DriveNum) then
  2148.         Result := dtRAM;
  2149.     end;
  2150.   end;
  2151. end;
  2152.  
  2153. begin
  2154.   { Set the button colors to an aquamarine color scheme for drives }
  2155.   ButtonColor := clTeal;
  2156.   ButtonHLColor := clAqua;
  2157.   ButtonSColor := clNavy;
  2158.   TextColor := clblack;
  2159.   { Set initial variables before looping for all drives }
  2160.   finished := false;
  2161.   DriveNum := 0;
  2162.   while not finished do
  2163.   begin
  2164.     { Start with no drive found }
  2165.     IconType := 0;
  2166.     { Call the Borland method to get the drive info }
  2167.     DriveType := FindDriveType(DriveNum);
  2168.     { Set its letter and make it uppercase }
  2169.     DriveChar := Chr(DriveNum + ord('a'));
  2170.     DriveChar := Upcase(DriveChar);
  2171.     { Assign an icon based on the drive type; if no drive exists type is nil }
  2172.     case DriveType of
  2173.       dtFloppy  : IconType := 1;
  2174.       dtFixed   : IconType := 2;
  2175.       dtNetwork : IconType := 3;
  2176.       dtCDROM   : IconType := 4;
  2177.       dtRAM     : IconType := 5;
  2178.     end;
  2179.     { Set to check next drive letter }
  2180.     DriveNum := DriveNum + 1;
  2181.     { But if no match then out of drives so set exit flag }
  2182.     if IconType = 0 then finished := true;
  2183.     { If drive was valid then set up the new FileIconPanel on the imported }
  2184.     { Scrollbox                                                            }
  2185.     if not finished then
  2186.     begin
  2187.       { Create the FileIconPanel and set its parent for memory mgmt and display}
  2188.       TheFIP := TFileIconPanel.Create( Self );
  2189.       TheFIP.Parent := Self;
  2190.       { Call its initialize method with imported position values and the   }
  2191.       { preset color scheme, a drive caption, and a minimum font. Note the }
  2192.       { setting of the ExtraData field to non-zero; this signals a drive   }
  2193.       { rather than a file being sent in.                                  }
  2194.       TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  2195.        (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize , 3 ,
  2196.         7 , ButtonColor, ButtonHLColor,
  2197.        ButtonSColor , TextColor , 'DRIVE ' + DriveChar + ':' , 'MS Serif' , [] ,
  2198.        IconType );
  2199.       { Increment the column counter; if it exceeds max move to new row      }
  2200.       { Note that these are 'var' parameters and will export final position. }
  2201.       XCounter := XCounter + 1;
  2202.       if XCounter > MaxIconsInARow then
  2203.       begin
  2204.         XCounter := 1;
  2205.         YCounter := YCounter + 1;
  2206.       end;
  2207.     end;
  2208.   end;
  2209. end;
  2210.  
  2211. { This procedure assigns colors to FIP's based on file attributes }
  2212. procedure TFileIconPanelScrollBox.GetColorsForFileIcon( TheFile : String;
  2213.            var BC , HC , SC , TC : TColor );
  2214. var AmADir      ,             { Booleans hold file attribs }
  2215.     AmAnArchive ,
  2216.     AmAVolumeId ,
  2217.     AmHidden    ,
  2218.     AmReadOnly  ,
  2219.     AmSystem      : Boolean;
  2220. begin
  2221.   { Make the call to internal fileworkbench to set attributes }
  2222.   TheFWB.GetFileAttributes( TheFile , AmADir , AmAnArchive , AmAVolumeId ,
  2223.    AmHidden , AmReadOnly , AmSystem );
  2224.   { Volume ID has no subtypes }
  2225.   if AmAVolumeID then
  2226.   begin
  2227.     BC := clOlive;
  2228.     HC := clYellow;
  2229.     SC := clBlack;
  2230.     TC := clWhite;
  2231.     exit;
  2232.   end;
  2233.   { Check all directory combinations }
  2234.   if AmADir then
  2235.   begin
  2236.     BC := clNavy;
  2237.     HC := clBlue;
  2238.     SC := clBlack;
  2239.     TC := clWhite;
  2240.     if AmHidden then
  2241.     begin
  2242.       if AmReadOnly then
  2243.       begin
  2244.         if AmSystem then
  2245.         begin { One HECK of a file! }
  2246.           BC := clBlack;
  2247.           HC := clSilver;
  2248.           SC := clGray;
  2249.           TC := clWhite;
  2250.         end
  2251.         else
  2252.         begin { Dir,RO,Hid }
  2253.           BC := clMaroon;
  2254.           HC := clFuchsia;
  2255.           SC := clGreen;
  2256.           TC := clWhite;
  2257.         end;
  2258.       end
  2259.       else
  2260.       begin { Dir,Hid }
  2261.         BC := clPurple;
  2262.         HC := clFuchsia;
  2263.         SC := clBlack;
  2264.         TC := clWhite;
  2265.       end;
  2266.     end
  2267.     else
  2268.     begin
  2269.       if AmReadOnly then
  2270.       begin
  2271.         if AmSystem then
  2272.         begin { Dir,RO,Sys }
  2273.           BC := clMaroon;
  2274.           HC := clLime;
  2275.           SC := clGreen;
  2276.           TC := clWhite;
  2277.         end
  2278.         else
  2279.         begin { Dir,RO }
  2280.           BC := clGreen;
  2281.           HC := clLime;
  2282.           SC := clBlack;
  2283.           TC := clWhite;
  2284.         end;
  2285.       end
  2286.       else
  2287.       begin
  2288.         if AmSystem then
  2289.         begin { Dir,Sys }
  2290.           BC := clMaroon;
  2291.           HC := clRed;
  2292.           SC := clBlack;
  2293.           TC := clWhite;
  2294.         end;
  2295.       end;
  2296.     end;
  2297.   end
  2298.   else { Archive Only; check all combinations }
  2299.   begin
  2300.     BC := clSilver;
  2301.     HC := clWhite;
  2302.     SC := clGray;
  2303.     TC := clBlack;
  2304.     if AmHidden then
  2305.     begin
  2306.       if AmReadOnly then
  2307.       begin
  2308.         if AmSystem then
  2309.         begin { Hid,RO,Sys }
  2310.           BC := clRed;
  2311.           HC := clLime;
  2312.           SC := clPurple;
  2313.           TC := clBlack;
  2314.         end
  2315.         else
  2316.         begin { RO,Hid }
  2317.           BC := clLime;
  2318.           HC := clFuchsia;
  2319.           SC := clMaroon;
  2320.           TC := clBlack;
  2321.         end;
  2322.       end
  2323.       else
  2324.       begin { Hid }
  2325.         BC := clFuchsia;
  2326.         HC := clWhite;
  2327.         SC := clPurple;
  2328.         TC := clBlack;
  2329.       end;
  2330.     end
  2331.     else
  2332.     begin
  2333.       if AmReadOnly then
  2334.       begin
  2335.         if AmSystem then
  2336.         begin { RO,Sys }
  2337.           BC := clRed;
  2338.           HC := clLime;
  2339.           SC := clMaroon;
  2340.           TC := clBlack;
  2341.         end
  2342.         else
  2343.         begin { RO }
  2344.           BC := clLime;
  2345.           HC := clWhite;
  2346.           SC := clGreen;
  2347.           TC := clBlack;
  2348.         end;
  2349.       end
  2350.       else
  2351.       begin
  2352.         if AmSystem then
  2353.         begin { System }
  2354.           BC := clRed;
  2355.           HC := clWhite;
  2356.           SC := clMaroon;
  2357.           TC := clBlack;
  2358.         end;
  2359.       end;
  2360.     end;
  2361.   end;
  2362. end;
  2363.  
  2364. { This procedure gets all icons for an given directory, including drives and }
  2365. { standard subdirectories. It does not get special combinations or h/ro/sys  }
  2366. procedure TFileIconPanelScrollbox.GetIconsForEntireDirectory(
  2367.             TargetPath  : String );
  2368. var Finished        : Boolean;         { Loop flag              }
  2369.     TheSR           : TSearchRec;      { Searchrecord for FF/FN }
  2370.     TheResult       : Integer;         { return variable        }
  2371.     TempPath        : String;          { path for FF/FN         }
  2372.     TheFIP          : TFileIconPanel;  { generic FIP holder     }
  2373.     RowCounter    ,                    { position in row of FIP }
  2374.     ColumnCounter   : Integer;         { position in col of FIP }
  2375.     ButtonColor   ,                    { main panel color       }
  2376.     ButtonHLColor ,                    { bright panel color     }
  2377.     ButtonSColor  ,                    { dark panel color       }
  2378.     Textcolor       : TColor;          { label text color       }
  2379.     IsADir ,                           { Variable for file attr }
  2380.     IsAnArchive ,
  2381.     IsAVolumeID,
  2382.     IsAReadOnlyFile,
  2383.     IsAHiddenFile ,
  2384.     IsASystemFile     : Boolean;
  2385.     MaxTextLength     : Integer;       { Used to safely set size}
  2386. begin
  2387.   { hide during refresh }
  2388.   Visible := false;
  2389.   { Get the icon sizes }
  2390.   TheFIP := TFileIconPanel.Create( Self );
  2391.   TheFIP.Parent := Self;
  2392.   TheFIP.FTheLabel.Canvas.Font.Name := 'MS Serif';
  2393.   TheFIP.FTheLabel.Canvas.Font.Size := 7;
  2394.   MaxTextLength := TheFIP.FTheLabel.Canvas.TextWidth( 'COMMAND.COM' );
  2395.   TheFIP.Free;
  2396.   TheIconSize := MaxTextLength + 13;
  2397.   TheIconSpacing := TheIconSize + 5;
  2398.   { Set up maximum icons per row based on screen size }
  2399.   MaxIconsInARow := ( Screen.Width div TheIconSpacing );
  2400.   { Set up the position counters }
  2401.   RowCounter := 1;
  2402.   ColumnCounter := 1;
  2403.   { Get the drives for the current machine }
  2404.   AddDriveIcons( ColumnCounter , RowCounter  );
  2405.   { Set up the initial variables }
  2406.   Finished := false;
  2407.   TempPath := TargetPath + '*.*';
  2408.   { Make the call to FindFirst set to get any file; will return '.' }
  2409.   { so discard it.                                                  }
  2410.   TheResult := FindFirst( TempPath , faAnyFile , TheSR );
  2411.   { loop through all files in the directory and look for directories }
  2412.   while not Finished do
  2413.   begin
  2414.     { Make call to FindNext, using only SearchRecord from FindFirst }
  2415.     TheResult := FindNext( TheSR );
  2416.     { A -1 result means no more files so exit }
  2417.     if TheResult < 0 then finished := true else
  2418.     begin
  2419.       { Otherwise check for a directory attribute }
  2420.       if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory ) =
  2421.        faDirectory ) then
  2422.       begin
  2423.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  2424.          ButtonHLColor , ButtonSColor , TextColor );
  2425.         { If found create a new FileIconPanel on the imported scrollbox }
  2426.         { Note sending 0 ExtraData parameter to indicate file not drive }
  2427.         TheFIP := TFileIconPanel.Create( Self );
  2428.         TheFIP.Parent := Self;
  2429.         TheFIP.Initialize((( ColumnCounter - 1 ) * TheIconSpacing ),
  2430.          (( RowCounter - 1  ) * TheIconSpacing ) , TheIconSize, TheIconSize ,
  2431.           3 , 7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  2432.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  2433.         { Increment column counter and move to new row if past limit }
  2434.         ColumnCounter := ColumnCounter + 1;
  2435.         if ColumnCounter > MaxIconsInARow then
  2436.         begin
  2437.           ColumnCounter := 1;
  2438.           RowCounter := RowCounter + 1;
  2439.         end;
  2440.       end;
  2441.     end;
  2442.   end;
  2443.   { Call FindClose for Windows NT/Windows 95 compatibility }
  2444.   FindClose( TheSR );
  2445.   { Set up new initialization variables }
  2446.   Finished := false;
  2447.   TempPath := TargetPath + '*.*';
  2448.   { Make needed call to FindFirst and discard '.' }
  2449.   TheResult := FindFirst( TempPath , faAnyFile , TheSR );
  2450.   while not Finished do
  2451.   begin
  2452.     { Loop through file again, this time getting only archive files }
  2453.     TheResult := FindNext( TheSR );
  2454.     { Result of -1 indicates no more files }
  2455.     if TheResult < 0 then Finished := true else
  2456.     begin
  2457.       { If faArchive file then add new FileIconPanel }
  2458.       TheFWB.GetFileAttributes(( Targetpath + TheSR.Name ) , IsADir ,
  2459.        IsAnArchive , IsAVolumeId , IsAHiddenFile , IsAReadOnlyFile ,
  2460.         IsASystemFile );
  2461.       if (( IsAnArchive ) and ( not IsADir )) then
  2462.       begin
  2463.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  2464.          ButtonHLColor , ButtonSColor , TextColor );
  2465.         { Initialize new FileIconPanel and call initialize, sending 0 ED }
  2466.         TheFIP := TFileIconPanel.Create( Self );
  2467.         TheFIP.Parent := Self;
  2468.         TheFIP.Initialize((( ColumnCounter - 1 ) * TheIconSpacing ),
  2469.          (( RowCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize ,
  2470.           3 , 7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  2471.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  2472.         { Increment column counter and if needed row counter }
  2473.         ColumnCounter := ColumnCounter + 1;
  2474.         if ColumnCounter > MaxIconsInARow then
  2475.         begin
  2476.           ColumnCounter := 1;
  2477.           RowCounter := RowCounter + 1;
  2478.         end;
  2479.       end;
  2480.     end;
  2481.   end;
  2482.   { Call findclose for w95 and exit }
  2483.   FindClose( TheSR );
  2484.   { Reset to visible }
  2485.   Visible := true;
  2486. end;
  2487.  
  2488. { Update method for FIPscrollbox }
  2489. procedure TFileIconPanelScrollBox.Update;
  2490. begin
  2491.   IconsNeedRefreshing := true;
  2492.   { Force a repaint }
  2493.   InvalidateRect( TheStoredHandle , nil , true );
  2494. end;
  2495.  
  2496. { Create method for FIPScrollbox }
  2497. constructor TFileIconPanelScrollBox.Create( AOwner : TComponent );
  2498. begin
  2499.   inherited Create( AOwner );
  2500.   TheFWB := TFileWorkBench.Create( Self );
  2501. end;
  2502.  
  2503. { This function returns the next selected file's name }
  2504. function TFileIconPanelScrollBox.GetNextSelection( SourceDirectory : String;
  2505.                            var CurrentItem : Integer ) : String;
  2506. var TheResult    : String;      { Holds result of function }
  2507.     TheComponent : TComponent;  { Used for typecast        }
  2508.     finished     : boolean;     { Loop control variable    }
  2509.     TheComponentCount : Integer;
  2510. begin
  2511.   TheComponentCount := ComponentCount;
  2512.   { If past end of components exit with no result }
  2513.   if CurrentItem > TheComponentCount then TheResult := '' else
  2514.   begin
  2515.     { Set loop counter and run till find match or run out }
  2516.     finished := false;
  2517.     while not finished do
  2518.     begin
  2519.       { Pull component out of the list and check it }
  2520.       TheComponent := Components[ CurrentItem - 1 ];
  2521.       { Increment counter for later }
  2522.       CurrentItem := CurrentItem + 1;
  2523.       { Do the typecast with AS }
  2524.       if TheComponent is TFileIconPanel then
  2525.       with TheComponent as TFileIconPanel do
  2526.       begin
  2527.         { If its selected make sure OK }
  2528.         if Selected then
  2529.         begin
  2530.           { Don't accept backup for this level of operation }
  2531.           if FTheLabel.Caption <> '..' then
  2532.           begin
  2533.             { Otherwise return the name and abort the loop }
  2534.             TheResult := FTheName;
  2535.             finished := true;
  2536.           end;
  2537.         end
  2538.         else
  2539.         begin
  2540.           { Check to see if out of components }
  2541.           if CurrentItem > TheComponentCount then
  2542.           begin
  2543.             { If so signal error and abort }
  2544.             TheResult := '';
  2545.             finished := true;
  2546.           end;
  2547.         end;
  2548.       end;
  2549.     end;
  2550.   end;
  2551.   GetNextSelection := TheResult;
  2552. end;
  2553.  
  2554. { This procedure places a selection of files in the display based on wildcards }
  2555. procedure TFileIconPanelScrollBox.DisplayRecursiveSearchResults(
  2556.            TheStartingDirectory : String );
  2557. var XCounter ,
  2558.     YCounter   : Integer;
  2559.  
  2560. { This procedure does a recursive file search by first getting all matches (in-}
  2561. { cluding directories) and adding them to the list. Then it checks for ALL the }
  2562. { subdirectories and does the same trick on them til there are no more matches }
  2563. { and no more subdirectories, at which point it exits and recurses back up.    }
  2564. procedure RecursiveFileSearch( TheWorkingDirectory : String; var XCounter ,
  2565.                                YCounter : Integer );
  2566.  
  2567. { VITAL!!! These variables MUST be local for recursrion to work! }
  2568. var
  2569.     Finished        : Boolean;         { Loop flag              }
  2570.     TheSR           : TSearchRec;      { Searchrecord for FF/FN }
  2571.     TheResult       : Integer;         { return variable        }
  2572.     TargetPath ,
  2573.     FileMask   ,
  2574.     TheStoredWorkingDirectory ,
  2575.     ModifiedDirectory  : String;       { path for FF/FN         }
  2576.     TheFIP          : TFileIconPanel;  { generic FIP holder     }
  2577.     ButtonColor   ,                    { main panel color       }
  2578.     ButtonHLColor ,                    { bright panel color     }
  2579.     ButtonSColor  ,                    { dark panel color       }
  2580.     Textcolor       : TColor;          { label text color       }
  2581.  
  2582. begin
  2583.   { Jump out if abort pressed }
  2584.   if GlobalAbortFlag then exit;
  2585.   { Set up the initial variables }
  2586.   Finished := false;
  2587.   TheStoredWorkingDirectory := TheWorkingDirectory;
  2588.   Targetpath := ExtractFilePath( TheWorkingDirectory );
  2589.   FileMask := ExtractFileName( TheWorkingDirectory );
  2590.   { Make the call to FindFirst set to get any file }
  2591.   TheResult := FindFirst( TheWorkingDirectory , faAnyFile , TheSR );
  2592.   if TheResult < 0 then finished := true;
  2593.   if (( TheSr.Name <> '.' ) and ( TheSr.Name <> '..' ) and ( TheResult >= 0 ))
  2594.   then begin
  2595.     if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory ) =
  2596.      faDirectory ) then
  2597.     begin { A directory }
  2598.       GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  2599.        ButtonHLColor , ButtonSColor , TextColor );
  2600.       { If found create a new FileIconPanel on the imported scrollbox }
  2601.       { Note sending 0 ExtraData parameter to indicate file not drive }
  2602.       TheFIP := TFileIconPanel.Create( Self );
  2603.       TheFIP.Parent := Self;
  2604.       TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  2605.        (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize , 3 ,
  2606.         7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor , TargetPath
  2607.          + TheSr.Name , 'MS Serif' , [] , 0 );
  2608.       { Increment column counter and move to new row if past limit }
  2609.       XCounter := XCounter + 1;
  2610.       if XCounter > MaxIconsInARow then
  2611.       begin
  2612.         XCounter := 1;
  2613.         YCounter := YCounter + 1;
  2614.       end;
  2615.     end
  2616.     else
  2617.     begin { A File }
  2618.       { Set up the default color scheme for files }
  2619.       GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  2620.        ButtonHLColor , ButtonSColor , TextColor );
  2621.       { If found create a new FileIconPanel on the imported scrollbox }
  2622.       { Note sending 0 ExtraData parameter to indicate file not drive }
  2623.       TheFIP := TFileIconPanel.Create( Self );
  2624.       TheFIP.Parent := Self;
  2625.       TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  2626.        (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize, TheIconSize , 3 ,
  2627.         7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor , TargetPath
  2628.          + TheSr.Name , 'MS Serif' , [] , 0 );
  2629.       { Increment column counter and move to new row if past limit }
  2630.       XCounter := XCounter + 1;
  2631.       if XCounter > MaxIconsInARow then
  2632.       begin
  2633.         XCounter := 1;
  2634.         YCounter := YCounter + 1;
  2635.       end;
  2636.     end;
  2637.   end;
  2638.   { loop through all files in the directory and look for matches }
  2639.   while not Finished do
  2640.   begin
  2641.     { Allow keyboard processing and jump out if c-break hit }
  2642.     Application.ProcessMessages;
  2643.     if GlobalAbortFlag then exit;
  2644.     { Make call to FindNext, using only SearchRecord from FindFirst }
  2645.     TheResult := FindNext( TheSR );
  2646.     { A -1 result means no more files so exit }
  2647.     if TheResult < 0 then finished := true else
  2648.     begin
  2649.       if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory ) =
  2650.        faDirectory ) then
  2651.       begin { A directory }
  2652.         { Set up the blue color scheme for directories }
  2653.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  2654.          ButtonHLColor , ButtonSColor , TextColor );
  2655.         { If found create a new FileIconPanel on the imported scrollbox }
  2656.         { Note sending 0 ExtraData parameter to indicate file not drive }
  2657.         TheFIP := TFileIconPanel.Create( Self );
  2658.         TheFIP.Parent := Self;
  2659.         TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  2660.          (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize , 3 ,
  2661.            7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  2662.             TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  2663.         { Increment column counter and move to new row if past limit }
  2664.         XCounter := XCounter + 1;
  2665.         if XCounter > MaxIconsInARow then
  2666.         begin
  2667.           XCounter := 1;
  2668.           YCounter := YCounter + 1;
  2669.         end;
  2670.       end
  2671.       else
  2672.       begin { A File }
  2673.         { Set up the default color scheme for files }
  2674.         GetColorsForFileIcon( TargetPath + TheSR.Name , ButtonColor ,
  2675.          ButtonHLColor , ButtonSColor , TextColor );
  2676.         { If found create a new FileIconPanel on the imported scrollbox }
  2677.         { Note sending 0 ExtraData parameter to indicate file not drive }
  2678.         TheFIP := TFileIconPanel.Create( Self );
  2679.         TheFIP.Parent := Self;
  2680.         TheFIP.Initialize((( XCounter - 1 ) * TheIconSpacing ),
  2681.          (( YCounter - 1  ) * TheIconSpacing ) , TheIconSize , TheIconSize , 3 ,
  2682.           7 , ButtonColor, ButtonHLColor , ButtonSColor , TextColor ,
  2683.            TargetPath + TheSr.Name , 'MS Serif' , [] , 0 );
  2684.         { Increment column counter and move to new row if past limit }
  2685.         XCounter := XCounter + 1;
  2686.         if XCounter > MaxIconsInARow then
  2687.         begin
  2688.           XCounter := 1;
  2689.           YCounter := YCounter + 1;
  2690.         end;
  2691.       end;
  2692.     end;
  2693.   end;
  2694.   { Call FindClose for Windows NT/Windows 95 compatibility }
  2695.   FindClose( TheSR );
  2696.   { Set up the variables to do recursive calls on all directories}
  2697.   Finished := false;
  2698.   ModifiedDirectory := ExtractFilePath( TheWorkingdirectory ) + '*.*';
  2699.   { Make the call to FindFirst set to get any file, ignore result }
  2700.   TheResult := FindFirst( ModifiedDirectory , faDirectory , TheSR );
  2701.   while not Finished do
  2702.   begin
  2703.     { Allow keyboard input and jump out if c-break hit }
  2704.     Application.ProcessMessages;
  2705.     if GlobalAbortFlag then exit;
  2706.     { Make call to FindNext, using only SearchRecord from FindFirst }
  2707.     TheResult := FindNext( TheSR );
  2708.     { A -1 result means no more files so exit }
  2709.     if TheResult < 0 then finished := true
  2710.     else
  2711.     begin
  2712.       if TheSR.Name <> '..' then { Ignore backup in this case }
  2713.       begin
  2714.         { Do second check due to bug in FindNext }
  2715.         if (( FileGetAttr( TargetPath + TheSR.Name ) and faDirectory )
  2716.         = faDirectory ) then
  2717.         begin
  2718.           { Set up modified directory to recurse into }
  2719.           ModifiedDirectory := ExtractFilePath( TheStoredWorkingDirectory ) +
  2720.            TheSR.Name + '\' + FileMask;
  2721.           { Perform the recursion }
  2722.           RecursiveFileSearch( ModifiedDirectory , XCounter , YCounter );
  2723.         end;
  2724.       end;
  2725.     end;
  2726.   end;
  2727. end;
  2728.  
  2729. begin
  2730.   { Keep the scrollbox from updating during refresh }
  2731.   Visible := false;
  2732.   { Make the clear call }
  2733.   ClearTheFIPs;
  2734.   XCounter := 1;
  2735.   YCounter := 1;
  2736.   { Get the drives for the current machine }
  2737.   AddDriveIcons( XCounter , YCounter );
  2738.   RecursiveFileSearch( TheStartingDirectory , XCounter , YCounter );
  2739.   { Make the scrollbox visible again }
  2740.   Visible := true;
  2741. end;
  2742.  
  2743. end.
  2744.