
{Unit LsFileExplorer26.pas}
{=============================================================================}
{
Archive    :- FileExpl.zip

Components :- TLsDirTree10, TLsDirTreeCombo26 and
              TLsFilelistView26 w/TLsFilelistViewPopUp26

Version    :- 2.60  For Delphi versions 2, 3, 4 & 5

Author     :- Leo D. Shih <ldshih@ecn.ab.ca>

------------------------------------------------------------------------------
DISCLAIMER :- These components are currently distributed as Freeware,
							without warranty of any kind, either expressed or implied.
							In no event shall the author be liable for any problems
							or damages that may result from the use of these components.

							Suggestions for improvement or bug-fixing will be welcome.
------------------------------------------------------------------------------

Brief Description
=================

TLsDirTree10
------------
TLsDirTree10 is a descendant of TreeView component, that displays the directory
structure of the File System. It also supports creating, renaming and deleting
directories through the use of its context menu.

TLsDirTreeCombo26
-----------------
TLsDirTreeCombo26 is a ComboBox with a dropdown TreeView, that displays a
hierarchical tree of directories of the File System.

TLsFilelistView26 w/TLsFilelistViewPopUp26
------------------------------------------
TLsFilelistView26 is a File ListView component. In addition to its normal
functions, It also encapsulates SHFileOperation and other Windows API
functions to perform various file management tasks, such as cut, copy, paste,
rename, delete, open, view and send_to operations on files.  It also provides
statistics on Disk-FreeSpace, Selected-Numbers and Selected-Size as those
available in the Windows Explorer.

TLsFilelistViewPopUp26 is LsFilelistView26's Context Menu, containing
commands that perform operations on files.

For further information please refer to LsFileExplorer26.txt
																																							}
{=============================================================================}


{$IFNDEF VER80} // If not Delphi 1     //53
	{$DEFINE D2_OR_HIGHER}
	{$IFNDEF VER90} // If not Delphi 2
		{$DEFINE D3_OR_HIGHER}
		{$IFNDEF VER100} // If not Delphi 3
			{$DEFINE BCB3_OR_HIGHER}
			{$IFNDEF VER110} // If not BCB 3
				{$DEFINE D4_OR_HIGHER}
				{$IFNDEF VER120} // If not Delphi 4
					{$DEFINE D5_OR_HIGHER}
				{$ENDIF}
			{$ENDIF}
		{$ENDIF}
	{$ENDIF}
{$ENDIF}


unit LsFileExplorer26;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Buttons,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, CommCtrl, FileCtrl, ShellAPI,
  ClipBrd, Menus,
  {$IFNDEF D3_OR_HIGHER}
  ShellObj, OLE2
  {$ELSE}
  ShlObj, ActiveX, ComObj
  {$ENDIF}
  {$IFDEF D4_OR_HIGHER},
  ImgList
  {$ENDIF}
  {$IFNDEF D5_OR_HIGHER},
  DsgnIntf
  {$ENDIF};


type

  TFileAttr = ( ftReadOnly, ftHidden, ftSystem, ftArchive, ftNormal );
  TFileType = set of TFileAttr;

  TDTFormat = ( dfMDY, dfDMY, dfYMD );
  TDateFormat = set of TDTFormat;

  TLsFileListView26 = class;
  TLsFileListViewPopUp26 = class;
  TLsDirTreeCombo26 = class;
  TLsDirTreePopUp10 = class;
  {$IFNDEF D5_OR_HIGHER}
  TAboutProperty = class;
  {$ENDIF}

  {*******************************************}
  {             TLsDirTreeView                }
  {  Drop-down TreeView of TLsDirTreeCombo26  }
  {*******************************************}

  TLsDirTreeView = class( TCustomTreeView )
  private
    TreeViewPath : string;
    FSelectedPath : string;
    FExpandRoot : Boolean;
    FMouseInControl : Boolean;
    {v0.40}
    FLastSelected: TTreeNode;
    {/v0.40}
    procedure CMMouseEnter( var Message : TMessage ); message CM_MOUSEENTER;
    procedure CMMouseLeave( var Message : TMessage ); message CM_MOUSELEAVE;
    procedure WMMouseMove( var Message : TWMMouseMove ); message WM_MOUSEMOVE;
    procedure WMLButtonDown( var Message : TWMLButtonDown ); message
      WM_LBUTTONDOWN;
    {v0.40}
    procedure WMLButtonDblClk( var Message : TWMLButtonDown ); message
      WM_LBUTTONDBLCLK;
    {/v0.40}
  protected
    {v0.40}
    {procedure DblClick; override;}
    {/v0.40}
    procedure CreateParams( var Params : TCreateParams ); override;
    procedure CreateWnd; override;
    procedure Expand( Node : TTreeNode ); override;
    procedure LoadDrives;
    procedure MakePath( Node : TTreeNode );
    procedure AddSubs( Path : string; Node : TTreeNode );
    procedure Expanding( Sender : TObject; Node : TTreeNode;
      var AllowExpansion : Boolean );
  end;

  {*******************************************}
  {            TLsDirTreeCombo26              }
  {*******************************************}

  TLsDirTreeCombo26 = class( TCustomEdit )
    Btn : TSpeedButton;
    Tree : TLsDirTreeView;
  private
    {$IFNDEF D5_OR_HIGHER}
    FAbout : TAboutProperty;
    {$ENDIF}
    FFileList : TLsFileListView26;
    FWinDir : string;
    ImageIndex : integer;
    ImagLst : TImageList;
    FCanvas : TControlCanvas;
  protected
    procedure CreateWnd; override;
    procedure Notification( AComponent : TComponent;
      Operation : TOperation ); override;
    procedure CreateWindowHandle( const Params : TCreateParams ); override;
    procedure CreateParams( var Params : TCreateParams ); override;
    procedure SetEditRect;
    procedure BtnClick( Sender : TObject );
    function GetFileList : TLsFileListView26;
    procedure SetFileList( Value : TLsFileListView26 );
    function GetBtnGlyph : TBitmap;
    procedure SetBtnGlyph( NewValue : TBitmap );
    function GetTreeHeight : Integer;
    procedure SetTreeHeight( newValue : Integer );
    function GetSelectedPath : string;
    procedure SetSelectedPath( Value : string );
    function GetExpandRoot : Boolean;
    procedure SetExpandRoot( Value : Boolean );
    function GetHideSelection : Boolean;
    Procedure SetHideSelection( Value : Boolean );
    procedure WMPaint( var Message : TWMPaint ); message WM_PAINT;
    procedure KeyDown( var Key : Word; Shift : TShiftState ); override; //52
    {v0.40}
    {procedure DblClick; override;}
    procedure SetSelectedPathFromTree;
    procedure UpdateText;
    {/v0.40}
  public
    { Public declarations }
    constructor Create( AOwner : TComponent ); override;
    destructor Destroy; override;
    procedure SetBounds( Left, Top, Width, Height : Integer ); override;
    procedure OpenPath( dPath : string );
    procedure ResetTreeView;
  published
    {$IFNDEF D5_OR_HIGHER}
    property About : TAboutProperty read FAbout write FAbout;
    {$ENDIF}
    property SelectedPath : string read GetSelectedPath write SetSelectedPath;
    property FileList : TLsFileListView26 read GetFileList write SetFileList;
    property ExpandRoot : Boolean read GetExpandRoot write SetExpandRoot
      default True;
    property HideSelection : Boolean Read GetHideSelection
      Write SetHideSelection Default True;
    property Align;
    property BorderStyle;
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragMode;
    property Enabled;
    property Font;
    property Height;
    property HelpContext;
    property Hint;
    property Left;
    property Name;
    property Glyph : TBitmap read GetBtnGlyph write SetBtnGlyph;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly; //53+
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Tag;
    property Top;
    property TreeHeight : Integer read GetTreeHeight write SetTreeHeight;
    property Visible;
    property Width;
    property OnChange;
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
    {$IFDEF D4_OR_HIGHER}
    property Anchors;
    property BiDiMode;
    property Constraints;
    {$ENDIF}
  end;

  {*******************************************}
  {             TLsDirTree10              //60}
  {*******************************************}

  TLsDirTree10 = class( TCustomTreeView )
  private
    FFileList : TLsFileListView26;
    FSelectedPath : string;
    FWinDir : string;
    ImagLst : TImageList;
    TreeViewPath : string;
    FPopUpMenu : TLsDirTreePopUp10;
    FPopUpMenuEnabled : Boolean;
    FIsNewFolder : Boolean;
    {$IFNDEF D5_OR_HIGHER}
    FAbout : TAboutProperty;
    {$ENDIF}
  protected
    procedure CreateWnd; override;
    procedure DestroyWnd; override;
    procedure SetSelectedPath( Value : string );
    procedure Expanding( Sender : TObject; Node : TTreeNode;
      var AllowExpansion : Boolean );
    procedure MouseDown( Button : TMouseButton;
      Shift : TShiftState; X, Y : Integer ); override;
    procedure LoadRoot;
    procedure LoadDrives;
    procedure Expand( Node : TTreeNode ); override;
    procedure MakePath( Node : TTreeNode );
    procedure AddSubs( Path : string; Node : TTreeNode );
    procedure KeyDown( var Key : Word; Shift : TShiftState ); override;
    //		procedure CNNotify( var Message : tWMNotify ); Message CN_NOTIFY;
    function CanEdit( Node : TTreeNode ) : Boolean; override;
    procedure Edit( const Item : TTVItem ); override;
    procedure SetPopUpMenuEnabled( Value : Boolean );
    procedure SetFileList( Value : TLsFileListView26 );
    function GetPathFromNode( Node : TTreeNode ) : string;
  public
    { Public declarations }
    constructor Create( AOwner : TComponent ); override;
    destructor Destroy; override;
    procedure ReLoad;
    procedure OpenPath( dPath : string );
    function AddNewNode( ParentNode : TTreeNode; NodeName : string ) :
      Boolean;
    function DeleteNode( Node : TTreeNode ) : Boolean;
  published
    {$IFNDEF D5_OR_HIGHER}
    property About : TAboutProperty read FAbout write FAbout;
    {$ENDIF}
    property FileList : TLsFileListView26 read FFileList write SetFileList;
    property SelectedPath : string read FSelectedPath write SetSelectedPath;
    property PopUpMenuEnabled : Boolean read FPopUpMenuEnabled
      write SetPopUpMenuEnabled default True;
    property Align;
    property BorderStyle;
    property Color;
    property Ctl3D;
    property DragCursor;
    property DragMode;
    property Enabled;
    property Font;
    property Height;
    property HelpContext;
    property HideSelection;
    property Hint;
    property Images;
    property Indent;
    property Items;
    property Left;
    property Name;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly;
    property ShowButtons;
    property ShowHint;
    property ShowLines;
    property ShowRoot;
    property SortType;
    property TabOrder;
    property TabStop;
    property Tag;
    property Top;
    property Visible;
    property Width;
    property OnChange;
    property OnChanging;
    property OnClick;
    property OnCollapsed;
    property OnCollapsing;
    property OnDblClick;
    property OnDeletion;
    property OnDragDrop;
    property OnDragOver;
    property OnEdited;
    property OnEditing;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnExpanded;
    property OnExpanding;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
  end;

  { ***** TLsDirTreePopUp10 ***** }

  TLsDirTreePopUp10 = class( TPopupMenu )
  private
    FDirTree : TLsDirTree10;

	protected
    function AddNewItem( const aCaption : string; aShortCut : TShortCut;
      aChecked, aEnabled : Boolean; aGroup : integer;
      aOnClick : TNotifyEvent; hCtx : word;
      const aName : string ) : TMenuItem;
		procedure SetDirTree( Value : TLsDirTree10 );
    procedure ItemOnClick( Sender : TObject );
  public
    constructor Create( AOwner : TComponent ); override;
    destructor Destroy; override;
    procedure BuildItems;
    procedure Popup( X, Y : integer ); override;
    property DirTree : TLsDirTree10 read FDirTree;
  end;



  {*******************************************}
  {           LsFileListView26                }
  {*******************************************}

  TLsFileListView26 = class( TCustomListView )
  private
    { Private declarations }
    FColumnWidths : record
            cwName : integer;
            cwSize : integer;
            cwType : integer;
            cwMod : integer;
            cwAttr : integer;
    end;
    {$IFNDEF D5_OR_HIGHER}
    FAbout : TAboutProperty;
    {$ENDIF}
    FDirTreeCombo : TLsDirTreeCombo26;
    FDirTree : TLsDirTree10;
    FDirectory : string;
    FDirectorySize : integer;
    FDateFormat : TDateFormat;
    FSelectedItem : string;
    FFileType : TFileType;
    FOpMode : Integer;
    FMask : string;
    FPopupMenu : TLsFileListViewPopUp26;
    FPopUpMenuEnabled : Boolean;
    FSelectedFiles : TStrings;
    FShowFolders : Boolean;
    FSortColumn : integer;
    FSortForward : boolean;
    OldFName : string;
    FDblClickEnabled : Boolean; //53

    function GetFreeSpace : Integer;
    function GetSelectedNum : Integer;
    function GetSelectedSize : Integer;

    procedure Createimages;
    procedure CompareFiles( Sender : TObject; Item1,
            Item2 : TListItem; Data : Integer; var Compare : Integer );
    procedure ColumnClick( Sender : TObject; Column : TListColumn );
    procedure SetPopUpMenuEnabled( Value : Boolean );
    procedure SetDblClickEnabled( Value : Boolean );
  protected
    { Protected declarations }
    function AddFiles( FileMask : string; Attr : DWORD ) : Boolean;
    function CanEdit( Item : TListItem ) : Boolean; override;
    function GetSelectedItem : string;
    function GetDirectory : string;

    procedure AddDrives;
    procedure Click; override;
    procedure CreateWnd; override;
    procedure CreateDriveColumns;
    procedure CreateFileColumns;
    procedure DblClick; override;
    procedure Edit( const Item : TLVItem ); override;
    procedure Loaded; override;
    procedure Keydown( var Key : Word; Shift : TShiftState ); override;
    procedure SetDateFormat( NewFmt : TDateFormat );
    procedure SetDirectory( NewDir : string );
    procedure SetDirTreeCombo( Val : TLsDirTreeCombo26 );
    procedure SetDirTree( VaL : TLsDirTree10 );
    procedure SetSelectedItem( NewItem : string );
    procedure SetFileType( NewFileType : TFileType );
    procedure SetMask( const NewMasks : string );
    procedure SetShowFolders( Value : Boolean );
    procedure Notification( AComponent : TComponent;
            Operation : TOperation ); override;
    procedure SendTo( SubItems : integer );
    procedure SendTo2( Path : string );
    procedure SendToPath( DestPath : string );
    procedure SendToDrive( DriveID : string );
  public
    { Public declarations }
    constructor Create( AOwner : TComponent ); override;
    destructor Destroy; override;
    procedure CutCopy( Mode : integer );
    procedure DeleteItems;
    procedure FindFile;
    procedure FileAttr;
    procedure NewFolder;
    procedure OneLevelUp;
    procedure OpenItem;
    procedure Paste;
    procedure RenameFile;
    procedure UpdateFileList;
    procedure ViewFile;
    procedure SetColumnWidth( Col_Name, Col_Size, Col_Type, Col_Mod,
            Col_Attr : integer );
    property DirectorySize : integer read FDirectorySize;
    property SelectedItem : string read GetSelectedItem write SetSelectedItem;
    property SelCount;
    property Selected;
  published
    { Published declarations }
    {$IFNDEF D5_OR_HIGHER}
    property About : TAboutProperty read FAbout write FAbout;
    {$ENDIF}
    property DateFormat : TDateFormat read FDateFormat write SetDateFormat
            default [ dfMDY ];
    property Directory : string read GetDirectory write SetDirectory;
    property DirTreeCombo : TLsDirTreeCombo26 read FDirTreeCombo
            write SetDirTreeCombo;
    property DirTree : TLsDirTree10 read FDirTree
            write SetDirTree;
    property DriveFreeSpace : Integer read GetFreeSpace;
    property DblClickEnabled : Boolean read FDblClickEnabled
            write SetDblClickEnabled default True;
    property FileType : TFileType read FFileType write SetFileType default
            [ ftNormal ];
    property Mask : string read FMask write SetMask;
    property PopUpMenuEnabled : Boolean read FPopUpMenuEnabled
            write SetPopUpMenuEnabled default True;
    property SelectedNumber : Integer read GetSelectedNum;
    property SelectedSize : Integer read GetSelectedSize;
    property ShowFolders : Boolean read FShowFolders write SetShowFolders
            default True;
    property Align;
    property BorderStyle;
    property Color;
    property Ctl3D;
    property Cursor;
    property Dragmode;
    property DragCursor;
    property Enabled;
    property Font;
    property Height;
    property HideSelection default False;
    property Hint;
    property IconOptions;
    property Items;
    property Left;
    property MultiSelect default True;
    property Name;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ReadOnly default False;
    property ShowColumnHeaders default True;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Tag;
    property Top;
    property ViewStyle default vsReport;
    property Visible;
    property Width;
    property OnChange;
    property OnChanging;
    property OnClick;
    property OnColumnClick;
    property OnCompare;
    property OnDblClick;
    property OnDeletion;
    property OnDragDrop;
    property OnDragOver;
    property OnEdited;
    property OnEditing;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnInsert;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDrag;
    {$IFDEF D3_OR_HIGHER}
    property HotTrack;
    property RowSelect default False;
    {$ENDIF}
    {$IFDEF D4_OR_HIGHER}
    property Anchors;
    property BiDiMode;
    property Constraints;
    property HotTrackStyles;
    {$ENDIF}
  end;

  { ====== TLsFileListViewPopUp26 ====== }

  TLsFileListViewPopUp26 = class( TPopupMenu )
  private
          SendToList : TStrings;
          FFileListView : TLsFileListView26;
          {$IFDEF D4_OR_HIGHER}
          FWinDir : string;
          ImagLst : TImageList;
          {$ENDIF}
  protected
          function AddNewItem( const aCaption : string; aShortCut : TShortCut;
                  aChecked, aEnabled : Boolean; aGroup : integer;
                  aOnClick : TNotifyEvent; hCtx : word;
                  const aName : string ) : TMenuItem;
          procedure SetFileListView( Value : TLsFileListView26 );
          procedure GetSendToSubMenu;
          procedure ItemOnClick( Sender : TObject );

  public
          constructor Create( AOwner : TComponent ); override;
          destructor Destroy; override;
          procedure BuildItems;
          procedure Popup( X, Y : integer ); override;
          property FileListView : TLsFileListView26 read FFileListView;
  end;

  {*******************************************}
  {             TAboutProperty                }
  {*******************************************}

  {$IFNDEF D5_OR_HIGHER}
  TAboutProperty = class( TPropertyEditor )
  public
          procedure Edit; override;
          function GetAttributes : TPropertyAttributes; override;
          function GetValue : string; override;
  end;
  {$ENDIF}

{*******************************************}
{          Global Functions                 }
{*******************************************}

function ExecuteFile( const Operation, FileName, Params, DefaultDir : string;
	ShowCmd : Integer ) : THandle;
function DoSHFileOp( Handle : THandle; OpMode : UInt; Src : string;
	Dest : string; var Aborted : Boolean ) : Boolean;
function AddNullToStr( Path : string ) : string;
function StrContains( Str1, Str2 : string ) : Boolean;
function BrowseForDir( const FormHandle : HWND; var DirPath : string ) :
	Boolean;
function numpos( a : char; b : string; c : integer ) : integer;
function getcount( a : char; b : string ) : integer;
function GetDiskSize( Root : string ) : LongInt;
function GetFreeDiskSize( Root : string ) : LongInt;
function DiskinDrive( Drive : Char; ShowMsg : word ) : Boolean;
function SlashSep( Path, FName : string ) : string;
function AddSlash( Path : string ) : string;
function DelSlash( Path : string ) : string;
function FileTimeToDateTimeStr( FileTime : TFileTime ) : string;
function FileDirExist( FDName : string ) : Boolean;
function GetNormalIcon( Path : string ) : integer;
function GetSelectedIcon( Path : string ) : Integer;


procedure Register;


implementation


const

	InvalidDOSChars = '\*?/="<>|:,;+^';
	DefaultMask = '*.*';
	FileOpMode : array[ 0..3 ] of UInt =
		( FO_COPY, FO_DELETE, FO_MOVE, FO_RENAME );

	FileExt : array[ 0..13 ] of string = ( '.C', '.CPP', '.DPK', '.DPR', '.H',
		'.INF', '.INI', '.PAS', '.PRG', '.TXT', '.DOC', '.RTF', '.WRI', '.BMP' );


	{***********************************************************************}
	{                        Global Functions                               }
	{***********************************************************************}

function ExecuteFile( const Operation, FileName, Params, DefaultDir : string;
	ShowCmd : Integer ) : THandle;
var
	zOperation : array[ 0..79 ] of Char;
	zFileName : array[ 0..79 ] of Char;
	zParams : array[ 0..79 ] of Char;
	zDir : array[ 0..79 ] of Char;
begin
	Result := ShellExecute( Application.Handle,
		StrPCopy( zOperation, Operation ),
		StrPCopy( zFileName, FileName ),
		StrPCopy( zParams, Params ),
		StrPCopy( zDir, DefaultDir ), ShowCmd );
	if Result <= 32 then
		MessageDlg( 'ERROR - Can''t ' + Operation + ' file  ' +
			FileName, mtError, [ mbOK ], 0 );
end; // ExecuteFile

function DoSHFileOp( Handle : THandle; OpMode : UInt; Src : string;
  Dest : string; var Aborted : Boolean ) : Boolean;
var
	ipFileOp : TSHFileOpStruct;
begin
	Src := AddNullToStr( Src );
	Dest := AddNullToStr( Dest );
  FillChar( ipFileOp, SizeOf( ipFileOp ), 0 );
  with ipFileOp do
  begin
    wnd := Handle;
		wFunc := OpMode;
		pFrom := pChar( Src );
    pTo := pChar( Dest );
    fFlags := FOF_ALLOWUNDO; //or FOF_RENAMEONCOLLISION;
    fAnyOperationsAborted := Aborted;
    hNameMappings := nil;
    lpszProgressTitle := '';
  end;
  Result := SHFileOperation( ipFileOp ) = 0;
  if ipFileOp.fAnyOperationsAborted = True then
    Result := False;
end; //DoSHFileOp

function AddNullToStr( Path : string ) : string;
begin
	Result := '';
  SetLength( Path, Succ( Length( Path ) ) );
  Path[ Length( Path ) ] := #0;
	Result := Path;
end; //AddnullToStr

function StrContains( Str1, Str2 : string ) : Boolean;
var
	i : Integer;
begin
  for i := 1 to Length( Str1 ) do
    if Pos( Str1[ i ], Str2 ) <> 0 then
    begin
      Result := True;
      Exit;
    end;
  Result := False;
end; //StringCountains

function BrowseForDir( const FormHandle : HWND; var DirPath : string ) :
  Boolean;
var
	pidl : PItemIDList;
	FBrowseInfo : TBrowseInfo;
  Success : Boolean;
  TitleName : string;
	Buffer : array[ 0..Max_Path ] of Char;
begin
  Result := False;
  ZeroMemory( @FBrowseInfo, SizeOf( FBrowseInfo ) );
  try
		GetMem( FBrowseInfo.pszDisplayName, MAX_PATH );
		FBrowseInfo.HWndOwner := FormHandle;
    TitleName := 'Please specify a directory';
    FBrowseInfo.lpszTitle := PChar( TitleName );
    pidl := SHBrowseForFolder( FBrowseInfo );
    if pidl <> nil then
    begin
      Success := SHGetPathFromIDList( pidl, Buffer );
			if Success then
      begin
        DirPath := Buffer;
				if DirPath[ Length( DirPath ) ] <> '\' then
          DirPath := DirPath + '\';
        result := True;
			end;
			GlobalFreePtr( pidl );
    end;
  finally
		if Assigned( FBrowseInfo.pszDisplayName ) then
      FreeMem( FBrowseInfo.pszDisplayName, Max_Path );
  end;
end; // BrowseForDir

function numpos( a : char; b : string; c : integer ) : integer;
var
  it : integer;
  az : integer;
begin
	result := maxint;
  if length( b ) > 0 then
  begin
    az := 0;
    for it := 1 to length( b ) do
      if b[ it ] = a then
			begin
        inc( az );
        if az = c then
				begin
					result := it;
          exit;
        end;
			end;
  end;
end; // numpos

function getcount( a : char; b : string ) : integer;
var
	it : integer;
begin
  result := 0;
  if length( b ) > 0 then
    for it := 1 to length( b ) do
      if b[ it ] = a then inc( result );
end; // getcount

function GetDiskSize( Root : string ) : LongInt;
var
	SpC,
    BpS,
    NfC,
		TnC : DWORD;
	DiskSize : Extended; //Double;              //53
begin
  GetDiskFreeSpace( PChar( Root ), SpC, BpS, NfC, TnC );
	DiskSize := TnC * SpC; //53
  DiskSize := ( DiskSize * BpS ) / 1024;
  Result := Round( DiskSize ); // Result in KB
end; // GetDiskSize

function GetFreeDiskSize( Root : string ) : LongInt;
var
  SpC, BpS,
    NfC, TnC : DWORD;
  FreeDiskSize : Extended; //Double;            //53
begin
  GetDiskFreeSpace( PChar( Root ), SpC, BpS, NfC, TnC );
  FreeDiskSize := Nfc * SpC;
	FreeDiskSize := ( FreeDiskSize * BpS ) / 1024;
	Result := Round( FreeDiskSize ); // Result in KB
end; // GetFreeDiskSize

function DiskinDrive( Drive : Char; ShowMsg : word ) : Boolean;
var
	ErrorMode : word;
begin
	if Drive in [ 'a'..'z' ] then
		Dec( Drive, $20 );
	if not ( Drive in [ 'A'..'Z' ] ) then
		Showmessage( 'Not a valid Drive ID' );
	ErrorMode := SetErrorMode( SEM_FailCriticalErrors );
	try
		if DiskSize( Ord( Drive ) - $40 ) = -1 then
		begin
			if ShowMsg > 0 then
			begin
				MessageBeep( MB_IconHand );
				ShowMessage( 'ERROR - There is no disk in Drive ' + Drive + #13 +
					'                or Drive ' + Drive + ' is not ready' );
			end;
			Result := False
		end
		else
			Result := True;
	finally
		SetErrorMode( ErrorMode );
	end;
end; // DiskinDrive

function SlashSep( Path, FName : string ) : string;
begin
	if ( Path = '' ) or ( FName = '' ) then exit;
	if Path[ Length( Path ) ] <> '\' then
    Result := Path + '\' + FName
	else
    Result := Path + FName;
end; // SlashSep

function AddSlash( Path : string ) : string;
begin
  if Path = '' then
    exit;
  if Path[Length(Path)] <> '\' then
    Result := Path + '\'
  else
    Result := Path;
end; // AddSlash

function DelSlash( Path : string ) : string;
begin
  Result := Path;
  if Path <> '' then
    if Path[Length( Path )] = '\' then
      Delete( Result, Length( Path ), 1 );
end; //DelSlash

function FileTimeToDateTimeStr( FileTime : TFileTime ) : string;
var
	LocFTime : TFileTime;
  SysTime : TSystemTime;
  DateStr : string;
  TimeStr : string;
  FDateTimeStr : string;
	Dt, Tm : TDateTime;
begin
  FileTimeToLocalFileTime( FileTime, LocFTime );
  FileTimeToSystemTime( LocFTime, SysTime );
  try
    with SysTime do
    begin
      Dt := EncodeDate( wYear, wMonth, wDay );
      DateStr := DateToStr( Dt );
      Tm := EncodeTime( wHour, wMinute, wSecond, wMilliseconds );
			Timestr := TimeToStr( Tm );
			FDateTimeStr := DateStr + ' ' + TimeStr;
    end;
    Result := FDateTimeStr;
	except
		Result := '';
  end;
end; // FileTimeToDateTimeStr

function FileDirExist( FDName : string ) : Boolean;
var
  SRec : TSearchRec;
  FName : string;
begin
	FillChar( SRec, SizeOf( TSearchRec ), 0 );
  Result := FindFirst( AddNullToStr( FDName ), faAnyFile or faDirectory, SRec )
    = 0;
  if Result then
  begin
    FName := ExtractFileName( DelSlash( FDName ) );
		if ( FName[ Length( FName ) ] = #0 ) then
      FName := Copy( FName, 1, Length( FName ) - 1 );
    ShowMessage( 'ERROR - "' + FName + '" already exists !' );
  end;
	SysUtils.FindClose( SRec );
end;

function GetNormalIcon( Path : string ) : integer;
var
  sfi : TShFileInfo;
begin
	SHGetFileInfo( Pchar( Path ), 0, sfi, SizeOf( TSHFileInfo ),
    SHGFI_SYSICONINDEX or SHGFI_SMALLICON );
  Result := sfi.iIcon;
end; // GetNormalIcon

function GetSelectedIcon( Path : string ) : Integer;
var
  sfi : TShFileInfo;
begin
	SHGetFileInfo( Pchar( Path ), 0, sfi, sizeOf( TSHFileInfo ),
    SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_OPENICON );
  Result := sfi.iIcon;
end; // GetSelectedIcon


{****************************************}
{            TAboutProperty              }
{****************************************}

{$IFNDEF D5_OR_HIGHER}

procedure TAboutProperty.Edit;
begin
	MessageDlg( 'TLsDirTree10, TLsDirTreeCombo26 and' + #13#10 +
    '               TLsFileListView26' + #13#10 +
    '                   Version 2.60 ' + #13#13#10 +
    '        © 1998-1999  Leo D. Shih' + #13#10 +
    '        e-mail:  ldshih@ecn.ab.ca',
		mtInformation, [ mbOk ], 0 );
end;

function TAboutProperty.GetAttributes : TPropertyAttributes;
begin
  Result := inherited GetAttributes + [ paDialog, paReadOnly ]
    - [ paSubProperties ];
end;

function TAboutProperty.GetValue : string;
begin
	Result := '(About)';
end;
{$ENDIF}

{*************************************************************************}
{                           TLsDirTreeCombo26                             }
{*************************************************************************}

{ ===== LsDirTreeView (Drop-down TreeView of TLsDirTreeCombo26 ) ===== }

procedure TLsDirTreeView.CreateParams( var Params : TCreateParams );
begin
  inherited CreateParams( Params );
  with Params do
  begin
    Style := Style or WS_BORDER;
    //    ExStyle := WS_EX_TOOLWINDOW or WS_EX_TOPMOST;  //60
    WindowClass.Style := CS_SAVEBITS;
  end;
end; // CreateParams

{v0.40}

{procedure TLsDirTreeView.DblClick;
begin
  inherited;
end;}
{/v0.40}

procedure TLsDirTreeView.CreateWnd;
begin
  inherited CreateWnd;
  Font.Size := 8;
  Font.Name := 'MS Sans Serif';
  Windows.SetParent( Handle, 0 );
  CallWindowProc( DefWndProc, Handle, wm_SetFocus, 0, 0 );
end; // CreateWnd

procedure TLsDirTreeView.CMMouseEnter( var Message : TMessage );
begin
  inherited;
  FMouseInControl := True;
  ReleaseCapture;
end; // CMMouseEnter

procedure TLsDirTreeView.CMMouseLeave( var Message : TMessage );
var
  x, y : integer;
  PtPos : TPoint;
begin
  inherited;
  FMouseInControl := False;
  if not visible then
  begin
    x := 0;
    y := 0;
    PtPos := Point( x, y );
    PtPos := ClientToScreen( PtPos );
    SetCaptureControl( ControlAtPos( PtPos, False ) );
  end
  else
    SetCaptureControl( Self );
end; // CMMouseLeave

procedure TLsDirTreeView.WMMouseMove( var Message : TWMMouseMove );
var
  TreeHitTest : THitTests;
begin
  inherited;
  {v0.40 ulantype}{/v0.40
  if FMouseInControl and Enabled then
  begin
    TreeHitTest := GetHitTestInfoAt( Message.XPos, Message.YPos );
    if htOnLabel in TreeHitTest then
      Selected := GetNodeAt( Message.XPos, Message.YPos );
  end;}
end; // WMMouseMove

{v0.40}
procedure TLsDirTreeView.WMLButtonDblClk( var Message : TWMLButtonDown );
begin
  inherited;
end;
{/v0.40}

procedure TLsDirTreeView.WMLButtonDown( var Message : TWMLButtonDown );
var {messages windows}
  HitTest : THitTests;
  DrvCh : Char;
begin
  inherited;
  case FMouseInControl of
    False :
      begin
        ReleaseCapture;
        Enabled := False;
        Visible := False;
      end;
    True :
      begin
        SendMessage( ( Owner as TLsDirTreeCombo26 ).Handle, WM_LBUTTONDOWN, 0, 0
           );
        HitTest := GetHitTestInfoAt( Message.XPos, Message.YPos );
        if ( htOnItem in HitTest )
        {v0.40} or (( htOnLabel in HitTest) and (Selected = FLastSelected)){/v0.40}
        then
        begin
          MakePath( Selected );

          if ( Selected = Items[ 0 ] ) then
            FSelectedPath := 'Drives'
          else
            FSelectedPath := TreeViewPath;

          with ( Owner as TLsDirTreeCombo26 ) do
          begin
            SetSelectedPath( FSelectedPath );
            ImageIndex := Tree.Selected.ImageIndex;
            {v0.40}
            UpdateText;
            {/v0.40
            Text := Selected.Text;}
          end;

          Enabled := False;
          Visible := False;

          if Selected.Level = 1 then
            if GetDriveType( PChar( FSelectedPath ) ) = DRIVE_REMOVABLE then
            begin
              DrvCh := FSelectedPath[ 1 ];
              if not DiskInDrive( DrvCh, 1 ) then
                exit;
            end;
        end; // Hittest
        {v0.40}
        FLastSelected := Selected;
        {/v0.40}
        ReleaseCapture;
      end;
  end; // Case
end; // WMLButtonDown

procedure TLsDirTreeView.Expand( Node : TTreeNode );
begin
  Items.BeginUpdate;
	Node.AlphaSort;
  Items.EndUpdate;
  inherited Expand( Node );
end; // Expand

procedure TLsDirTreeView.LoadDrives;
var
  Drives : set of 0..25;
  ADrive : integer;
  DriveLetter : char;
  DriveString : string;
  DrvName : string;
  Sfi : TSHFileInfo;
  Root : TTreenode;
  idRoot : PItemIDList;
begin
	Root := nil;
  Items.BeginUpdate;
  Items.Clear;
	if SHGetSpecialFolderLocation( Handle, CSIDL_DRIVES, idRoot ) = NOERROR then
		if SHGetFileInfo( PChar( idRoot ), 0, Sfi, SizeOf( TSHFileInfo ), SHGFI_PIDL
      or
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_DISPLAYNAME ) <> 0 then
		begin
      Root := items.AddFirst( nil, Sfi.szDisplayName );
      Root.ImageIndex := Sfi.iIcon;
      Root.SelectedIndex := Sfi.iIcon;
    end;
  Integer( Drives ) := GetLogicalDrives;
	for ADrive := 0 to 25 do
  begin
    if ( ADrive in Drives ) then
    begin
      DriveLetter := Chr( ADrive + ord( 'A' ) );
      DriveString := DriveLetter + ':\';
      SHGetFileInfo( PChar( DriveString ), 0, Sfi, SizeOf( Sfi ),
        SHGFI_DISPLAYNAME );
      DrvName := Copy( Sfi.szDisplayName, 1, ( Pos( '(', Sfi.szDisplayName ) - 1
         ) );
			with Items do
      begin
        AddChild( Root, ' (' + DriveLetter + ':)  ' + DrvName );
				Items[ Count - 1 ].HasChildren := true;
				Items[ Count - 1 ].ImageIndex := GetNormalIcon( DriveString );
        Items[ Count - 1 ].SelectedIndex := GetSelectedIcon( DriveString );
      end;
		end;
  end;
  Items.EndUpdate;
end; // LoadDrives

procedure TLsDirTreeView.MakePath( Node : TTreeNode );

  procedure MakeSubPath;
  begin
    if Node.Level = 1 then
      TreeViewPath := Copy( Node.Text, 3, 2 ) + '\' + TreeViewPath
    else if Node.Level > 1 then
      if TreeViewPath = '' then
        TreeViewPath := Node.Text
      else
        TreeViewPath := Node.Text + '\' + TreeViewPath;
  end; // MakeSubPath

begin
  TreeViewPath := '';
  MakeSubPath;
  while Node.Parent <> nil do
  begin
    Node := Node.Parent;
    MakeSubPath;
  end;
end; // MakePath

procedure TLsDirTreeView.AddSubs( Path : string; Node : TTreeNode );
var
  ANode : TTreeNode;
  APath : string;
  hFindFile : THandle;
  Win32FD : TWin32FindData;

  function IsDirectory( dWin32FD : TWin32FindData ) : Boolean;
  var
    FName : string;
  begin
    FName := StrPas( dWin32FD.cFileName );
    with dWin32FD do
      Result := ( dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY =
        FILE_ATTRIBUTE_DIRECTORY ) and ( FName <> '.' ) and ( FName <> '..' );
  end; // IsDirectory

  function HasSubs( sPath : string ) : Boolean;
  var
    sAPath : string;
    shFindFile : THandle;
    sWin32FD : TWin32FindData;
  begin
    Result := False;
    sAPath := sPath;
    sAPath := AddSlash( sAPath );
    shFindFile := FindFirstFile( PChar( sAPath + '*.*' ), sWin32FD );
    if shFindFile <> INVALID_HANDLE_VALUE then
    try
      repeat
        if IsDirectory( sWin32FD ) then
        begin
          Result := True;
          Break;
        end;
      until not FindNextFile( shFindFile, sWin32FD );
    finally
      Windows.FindClose( shFindFile );
    end;
  end; // HasSubs

begin
  APath := Path;
  APath := AddSlash( APath );
  hFindFile := FindFirstFile( PChar( APath + '*.*' ), Win32FD );
  if hFindFile <> INVALID_HANDLE_VALUE then
  try
    repeat
      if IsDirectory( Win32FD ) then
      begin
        ANode := Items.AddChild( Node, Win32FD.cFileName );
        ANode.HasChildren := HasSubs( APath + Win32FD.cFileName );
        ANode.ImageIndex := GetNormalIcon( APath + Win32FD.cFileName );
        ANode.SelectedIndex := GetSelectedIcon( APath + Win32FD.cFileName );
      end;
    until not FindNextFile( hFindFile, Win32FD );
  finally
    Windows.FindClose( hFindFile );
  end;
end; // AddSubs

procedure TLsDirTreeView.Expanding( Sender : TObject; Node : TTreeNode;
	var AllowExpansion : Boolean );
begin
  if Node.GetFirstChild = nil then
  begin
    MakePath( Node );
    Node.HasChildren := false;
    AddSubs( TreeViewPath, Node );
    Node.AlphaSort;
  end;
end; // Expending

///// End of TLsDirTreeView /////


{ ====== TLsDirTreeCombo26 ====== }
{
procedure TLsDirTreeCombo26.DblClick;
begin
  inherited;
end;
 }
procedure TLsDirTreeCombo26.CreateWnd;
begin
  inherited CreateWnd;
  SetEditRect;
end; // CreateWnd

procedure TLsDirTreeCombo26.CreateParams( var Params : TCreateParams );
begin
  inherited CreateParams( Params );
  Params.style := Params.style or ES_MULTILINE or WS_CLIPCHILDREN;
end; // CrateParams

procedure TLsDirTreeCombo26.CreateWindowHandle( const Params : TCreateParams );
begin
  inherited CreateWindowHandle( Params );

  Font.Name := 'MS Sans Serif';
  Font.Size := 8;

  with Btn do
  begin
    Top := 0;
    width := 17;
    Left := 174;
    Height := 17;
    Cursor := crArrow;
    Down := False;
    OnClick := BtnClick;
    {$IFDEF D3_OR_HIGHER}
    Glyph.Handle := LoadBitmap( 0, pChar( OBM_COMBO ) );
    {$ENDIF}
    NumGlyphs := 1;
  end; //Btn

  with Tree do
  begin
    Left := 0;
    Top := 0;
    Width := 0;
    BorderStyle := bsSingle;
    Ctl3D := False;
    LoadDrives;
    OnExpanding := Expanding;
    ExpandRoot := True;
    ReadOnly := True;
    Enabled := False;
    Visible := False;
  end; // Tree

  if Tree.Selected = nil then
  begin
    ImageIndex := Tree.Items[ 0 ].ImageIndex;
    Text := Tree.Items[ 0 ].Text;
  end;
end; // CreateWindowHandle

constructor TLsDirTreeCombo26.Create;
var
  sfi : TShFileInfo;
begin
  inherited Create( AOwner );
  Width := 216;
  Height := 21;
  TabOrder := 0;
  ReadOnly := True; //53+
  FCanvas := TControlCanvas.Create;
  FCanvas.Control := self;

  Btn := TSpeedButton.Create( Self );
  Btn.Parent := Self;

  Tree := TLsDirTreeView.Create( Self );
  with Tree do begin
    Parent := Self;
    Top := Self.Top + Self.Height;
    Height := 240;
  end;

  ImagLst := TImageList.Create( self );
  try
    SetLength( FWinDir, MAX_PATH );
    SetLength( FWinDir, GetWindowsDirectory( PChar( FWinDir ), MAX_PATH ) );
    if FWinDir[Length( FWinDir )] <> '\' then
      FWinDir := FWinDir + '\';
    ImagLst.Handle := SHGetFileInfo( PChar( FWinDir ), 0, sfi, sizeOf( sfi ),
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON );
    ImagLst.ShareImages := True;
    ImagLst.BlendColor := clHighLight;
  finally
    Tree.Images := ImagLst;
  end;
end; // Create

destructor TLsDirTreeCombo26.destroy;
begin
  Tree.Items.Clear;
  ImagLst.Free;
  inherited Destroy;
end; // destroy

procedure TLsDirTreeCombo26.SetEditRect;
var
  Loc : TRect;
begin
  if ( ImageIndex >= 0 ) and ( ImageIndex < Tree.Images.Count ) then
  begin
    SetRect( Loc, 23, 0, ClientWidth - Btn.Width - 2, ClientHeight + 1 );
    SendMessage( Handle, EM_SETRECTNP, 0, LongInt( @Loc ) );
  end else
  begin
    SetRect( Loc, 0, 0, ClientWidth - Btn.Width - 2, ClientHeight + 1 );
    SendMessage( Handle, EM_SETRECTNP, 0, LongInt( @Loc ) );
  end;
end; // SetEditRect

procedure TLsDirTreeCombo26.BtnClick( Sender : TObject );
var
  CP, SP : TPoint;
begin
  CP.X := Left;
  CP.Y := Top + Height;
  //  SP := (Owner as TForm).ClientToScreen(CP);  //51
  SP := Parent.ClientToScreen( CP );
  with Tree do
  begin
    Left := SP.X;
    Top := SP.Y;
    Width := Self.Width;
    if Enabled = False then
    begin
      Enabled := True;
      Visible := True;
      BringToFront; //60
      SetCaptureControl( Tree );
    end else
    begin
      SendToBack; //60
      Enabled := False;
      Visible := False;
      ReleaseCapture;
    end;
  end;
end; // BtnClick

procedure TLsDirTreeCombo26.SetBounds( Left, Top, Width, Height : Integer );
begin
  case Parent <> nil of
    True :
      begin
        inherited SetBounds( Left, Top, Width, Height );
        with Btn do
        begin
          Left := Self.Width - Btn.Width - 4;
          Height := Self.Height - 4;
        end;
        SetEditRect;
      end;
    False : inherited SetBounds( Left, Top, Width, Height );
  end;
end; // SetBounds

procedure TLsDirTreeCombo26.OpenPath( dPath : string );
var
  CurItem : TTreeNode;
  count : Integer;
  TempPath : string;
  CurPath : string;
  FullPath : string; //51
begin
  if ( dPath = '' ) or ( Length( dPath ) = 1 ) then
    exit; //53
  if not DirectoryExists( dPath ) then
    exit; //53
  FullPath := AddSlash( dPath ); //51
  with Tree do begin
    CurItem := Items[ 0 ];
    if CurItem.Expanded then
      CurItem.Collapse( True );
    CurItem := Items.GetFirstNode;
    Items.BeginUpdate;
    {v0.32}
    dPath := FullPath;
    {/v0.32}
    while Pos( '\', dPath ) > 0 do
    begin
      count := Pos( '\', dPath );
      tempPath := Copy( dPath, 1, count );
      dPath := Copy( dPath, count + 1, Length( dPath ) );
      CurItem := CurItem.getFirstChild;
      while CurItem <> nil do begin
        if CurItem.Level = 1 then
          CurPath := Copy( CurItem.Text, 3, 2 ) + '\'
        else if CurItem.Level > 1 then
          CurPath := CurItem.Text + '\';

        if AnsiCompareText( CurPath, TempPath ) = 0 then //51
        begin
          CurItem.Selected := True;
          CurItem.Expand( False );
          Break;
        end;
        CurItem := CurItem.GetNext;
        if CurItem = nil then
          exit;
      end;
    end;
    Items.EndUpdate;
  end;
  ImageIndex := Tree.Selected.ImageIndex;
  {v0.40}{/v0.40
  Text := CurItem.Text;}
  if AnsiCompareText( Tree.FSelectedPath, FullPath ) <> 0 then //51
    Tree.FSelectedPath := FullPath; //51
  {v0.40}
  UpdateText;
  {/v0.40}
end; // OpenPath

procedure TLsDirTreeCombo26.ResetTreeView;
begin
  with Tree do
  begin
    Items.BeginUpdate;
    try
      Selected := nil;
      Items.Clear;
      LoadDrives;
      OnExpanding := Expanding;
    finally
      Items.EndUpdate;
    end;
  end;
end; // ResetTreeView

procedure TLsDirTreeCombo26.WMPaint( var Message : TWMPaint );
var
  Img : TCustomImageList;
  YPos : integer;
begin
  inherited PaintHandler( Message );
  Img := Tree.Images;
  if ( ImageIndex >= 0 ) and ( ImageIndex < Tree.Images.Count ) then
  begin
    YPos := ClientHeight div 2 - 8;
    Img.Draw( FCanvas, 5, YPos, ImageIndex );
  end;
end; // WMPaint

function TLsDirTreeCombo26.GetSelectedPath : string;
begin
  GetSelectedPath := Tree.FSelectedPath;
end; // GetSelectedPath

procedure TLsDirTreeCombo26.SetSelectedPath( Value : string );
begin
  if AnsiCompareText( Tree.FSelectedPath, Value ) <> 0 then
    Tree.FSelectedPath := Value;
  if FFileList <> nil then
    FFileList.Directory := Tree.FSelectedPath;
end; // SetSelectedPath

function TLsDirTreeCombo26.GetFileList : TLsFileListView26;
begin
  GetFileList := FFileList;
end; // GetFileList

procedure TLsDirTreeCombo26.SetFileList( Value : TLsFileListView26 );
begin
  if FFileList <> Value then
    FFileList := Value;
  //  if (Tree.FSelectedPath <> '') then                       //52
  if ( FFileList <> nil ) and ( Tree.FSelectedPath <> '' ) then
  begin
    FFileList.Directory := Tree.FSelectedPath;
    FFileList.UpdateFileList;
  end;
end; // SetFileList

function TLsDirTreeCombo26.GetExpandRoot : Boolean;
begin
  GetExpandRoot := Tree.FExpandRoot;
end; // GetExpandRoot

procedure TLsDirTreeCombo26.SetExpandRoot( Value : Boolean );
begin
  Tree.FExpandRoot := Value;
  with Tree do
    if FExpandRoot and Assigned( Items[ 0 ] ) then
      Items[ 0 ].Expand( False );
end; // SetExpandRoot

procedure TLsDirTreeCombo26.Notification( AComponent : TComponent;
  Operation : TOperation );
begin
  inherited Notification( AComponent, Operation );
  if ( Operation = opRemove ) and ( AComponent = FFileList ) then
    FFileList := nil;
end; // Notification

function TLsDirTreeCombo26.GetBtnGlyph : TBitmap;
begin
  GetBtnGlyph := Btn.Glyph;
end; // GetBtnGlyph

procedure TLsDirTreeCombo26.SetBtnGlyph( NewValue : TBitmap );
begin
  if NewValue <> nil then
    Btn.Glyph.Assign( NewValue );
end; // SetBtnGlyph

function TLsDirTreeCombo26.GetTreeHeight : integer;
begin
  GetTreeHeight := Tree.Height;
end; // GetTreeHeight

procedure TLsDirTreeCombo26.SetTreeHeight( newValue : Integer );
begin
  Tree.Height := newValue;
end; // SetTreeHeight

function TLsDirTreeCombo26.GetHideSelection : Boolean;
begin
  GetHideSelection := Tree.HideSelection;
end;

Procedure TLsDirTreeCombo26.SetHideSelection( Value : Boolean );
begin
  Tree.HideSelection := Value;
end;

procedure TLsDirTreeCombo26.KeyDown( var Key : Word; Shift : TShiftState );
var
  CurItem : TTreeNode;
begin //52
  case Key of
    VK_RIGHT : Tree.Selected.Expand( False ); //52 Expand Selected Node
    VK_LEFT : //52 Collapse Selected Node
    begin
      with Tree do begin
        if Selected.Expanded then
          Selected.Collapse( True );
        if ( Selected.getPrevSibling = Items[ 0 ] ) or
           ( Selected.GetPrevVisible = Items[ 0 ] ) or
           ( Selected = Items[ 0 ] )
        then
          exit;
        CurItem := Selected.GetPrevVisible;
        CurItem.Selected := True;
      end;
    end;
    VK_F4 : //52 Activate LsDirTreeView
      begin
        BtnClick( Self );
        if Tree.Visible then
          Tree.SetFocus;
      end;
    VK_ESCAPE : //52 Close LsDirTreeView
      begin
        if Tree.Enabled = True then
        begin
          Tree.Enabled := False;
          Tree.Visible := False;
        end;
      end;
    VK_DOWN : //52 Move to nextChild or nextVisible
      begin
        with Tree do
        begin
          if ( Selected.GetNext = nil ) or
            ( Selected.getNextVisible = nil ) then exit; //53
          if Selected.Expanded then
            CurItem := Selected.GetNext
          else
            CurItem := Selected.getNextVisible;
          CurItem.Selected := True;
        end;
      end;
    VK_UP : //52 Move to prevChild or prevVisible
      begin
        with Tree do
        begin
          if Selected = Items[0] then exit;
          CurItem := Selected.GetPrevVisible;
          CurItem.Selected := True;
        end;
      end;
    VK_RETURN : //52 set the SelectedPath
      begin
        {v0.40}
        SetSelectedPathFromTree;
        {/v0.40
        with Tree do
        begin
          MakePath( Selected );
          if ( Selected = Items[ 0 ] ) then
            FSelectedPath := 'Drives'
          else
            FSelectedPath := TreeViewPath;
          SetSelectedPath( FSelectedPath );
          SendToBack;
          Enabled := False;
          Visible := False;
          if Selected.Level = 1 then
            if GetDriveType( PChar( FSelectedPath ) ) = DRIVE_REMOVABLE then
            begin
              if not DiskInDrive( FSelectedPath[ 1 ], 1 ) then
                exit;
            end;
        end;
        Text := Tree.Selected.Text;}
      end; //VK_Return
  end; // case
  inherited KeyDown( Key, Shift );
end; //52 Keydown

{v0.40}
procedure TLsDirTreeCombo26.UpdateText;
begin
  Text := MinimizeName(Tree.FSelectedPath, Tree.Canvas, ClientWidth - 2 * Btn.Width - 2);
  {Text := Tree.Selected.Text;}
end;

procedure TLsDirTreeCombo26.SetSelectedPathFromTree;
begin
  with Tree do
  begin
    MakePath( Selected );
    if ( Selected = Items[ 0 ] ) then
      FSelectedPath := 'Drives'
    else
      FSelectedPath := TreeViewPath;
    SetSelectedPath( FSelectedPath );
    SendToBack;
    Enabled := False;
    Visible := False;
    if Selected.Level = 1 then
      if GetDriveType( PChar( FSelectedPath ) ) = DRIVE_REMOVABLE then
      begin
        if not DiskInDrive( FSelectedPath[ 1 ], 1 ) then
          exit;
      end;
  end; {sysutils filectrl}
  UpdateText;
  {Text := Tree.Selected.Text;}
end;
{/v0.40}

/////End of TLsDirTreeCombo26/////

{************************************************************************}
{                         TLsDirTree10                              //60 }
{************************************************************************}

procedure TLsDirTree10.CreateWnd;
begin
  inherited CreateWnd;
  CallWindowProc( DefWndProc, Handle, WM_SETFOCUS, 0, 0 );
	if not ( csLoading in ComponentState ) then
    LoadRoot;
end; //CreateWnd

procedure TLsDirTree10.DestroyWnd;
begin
  inherited DestroyWnd;
end; //DestroyWnd

constructor TLsDirTree10.Create;
var
  sfi : TShFileInfo;
begin
	inherited Create( AOwner );
  Font.size := 8;
	Font.name := 'MS Sans Serif';
	Width := 180;
  Height := 120;

  ImagLst := TImageList.Create( self );
  try
    SetLength( FWinDir, MAX_PATH );
    Setlength( FWinDir, GetWindowsDirectory( PChar( FWinDir ), MAX_PATH ) );
		FWinDir := AddSlash( FWinDir );
    ImagLst.Handle := SHGetFileInfo( PChar( FWinDir ), 0, sfi, sizeOf( sfi ),
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON );
    ImagLst.ShareImages := True;
    ImagLst.BlendColor := clHighLight;
  finally
    Images := ImagLst;
  end;

	FPopupMenu := TLsDirTreePopUp10.Create( Self );
  FPopupMenu.BuildItems;
  FPopupMenu.AutoPopup := True;
  FPopupMenu.FDirTree := Self;
	PopupMenu := FPopupMenu;
  FPopUpMenuEnabled := True;

	OnExpanding := Expanding;
  ReadOnly := False;
  SortType := stNone;
  HideSelection := False;
  FIsNewFolder := False;
end; //Create

destructor TLsDirTree10.Destroy;
begin
  ImagLst.Free;
  inherited;
end; //Destroy

procedure TLsDirTree10.LoadRoot;
var
  Sfi : TSHFileInfo;
	Root : TTreenode;
  idRoot : PItemIDList;
begin
  Items.BeginUpdate;
	Items.Clear;
  if SHGetSpecialFolderLocation( Handle, CSIDL_DRIVES, idRoot ) = NOERROR then
		if SHGetFileInfo( PChar( idRoot ), 0, Sfi, SizeOf( TSHFileInfo ), SHGFI_PIDL
			or
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_DISPLAYNAME ) <> 0 then
    begin
      Root := items.AddFirst( nil, Sfi.szDisplayName );
      Root.ImageIndex := Sfi.iIcon;
      Root.SelectedIndex := Sfi.iIcon;
    end;
	Items.EndUpdate;
end; //LoadRoot

procedure TLsDirTree10.LoadDrives;
var
  Drives : set of 0..25;
  ADrive : integer;
  DriveLetter : char;
  DriveString : string;
	DrvName : string;
  Sfi : TSHFileInfo;
begin
  Items.BeginUpdate;
	Integer( Drives ) := GetLogicalDrives;
  for ADrive := 0 to 25 do
	begin
		if ADrive in Drives then
    begin
      DriveLetter := Chr( ADrive + ord( 'A' ) );
      DriveString := DriveLetter + ':\';
      SHGetFileInfo( PChar( DriveString ), 0, Sfi, SizeOf( Sfi ),
        SHGFI_DISPLAYNAME );
      DrvName := Copy( Sfi.szDisplayName, 1, ( Pos( '(', Sfi.szDisplayName ) - 1
				 ) );
      with Items do
      begin
        AddChild( Items[ 0 ], ' (' + DriveLetter + ':)  ' + DrvName );
        ShowButtons := True;
        Items[ Count - 1 ].HasChildren := true;
        Items[ Count - 1 ].ImageIndex := GetNormalIcon( DriveString );
        Items[ Count - 1 ].SelectedIndex := GetSelectedIcon( DriveString );
      end;
		end;
  end;
  Items.EndUpdate;
end; //LoadDrives

procedure TLsDirTree10.MakePath( Node : TTreeNode );

	procedure MakeSubPath;
  begin
    if Node.Level = 1 then
      TreeViewPath := Copy( Node.Text, 3, 2 ) + '\' + TreeViewPath
    else if Node.Level > 1 then
      if TreeViewPath = '' then
        TreeViewPath := Node.Text
			else
        TreeViewPath := Node.Text + '\' + TreeViewPath;
  end; //MakeSubPath

begin
  TreeViewPath := '';
  MakeSubPath;
  while Node.Parent <> nil do
  begin
		Node := Node.Parent;
    MakeSubPath;
  end;
end; //MakePath

procedure TLsDirTree10.AddSubs( Path : string; Node : TTreeNode );
var
	ANode : TTreeNode;
  APath : string;
  hFindFile : THandle;
  Win32FD : TWin32FindData;

  function IsDirectory( dWin32FD : TWin32FindData ) : Boolean;
  var
		FName : string;
  begin
    FName := StrPas( dWin32FD.cFileName );
    with dWin32FD do
      Result := ( dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY =
        FILE_ATTRIBUTE_DIRECTORY ) and ( FName <> '.' ) and ( FName <> '..' );
  end; //IsDirectory

  function HasSubs( sPath : string ) : Boolean;
	var
    sAPath : string;
    shFindFile : THandle;
    sWin32FD : TWin32FindData;
	begin
    Result := False;
		sAPath := sPath;
		sAPath := AddSlash( sAPath );
    shFindFile := FindFirstFile( PChar( sAPath + '*.*' ), sWin32FD );
    if shFindFile <> INVALID_HANDLE_VALUE then
    try
      repeat
        if IsDirectory( sWin32FD ) then
        begin
					Result := True;
          Break;
        end;
      until not FindNextFile( shFindFile, sWin32FD );
    finally
      Windows.FindClose( shFindFile );
    end;
  end; //HasSubs

begin
  APath := Path;
  APath := AddSlash( APath );
  hFindFile := FindFirstFile( PChar( APath + '*.*' ), Win32FD );
	if hFindFile <> INVALID_HANDLE_VALUE then
  try
		repeat
			if IsDirectory( Win32FD ) then
      begin
        ANode := Items.AddChild( Node, Win32FD.cFileName );
        ANode.HasChildren := HasSubs( APath + Win32FD.cFileName );
        ANode.ImageIndex := GetNormalIcon( APath + Win32FD.cFileName );
        ANode.SelectedIndex := GetSelectedIcon( APath + Win32FD.cFileName );
      end;
		until not FindNextFile( hFindFile, Win32FD );
  finally
    Windows.FindClose( hFindFile );
  end;
end; //addSubs

procedure TLsDirTree10.ReLoad;
begin
  Items.BeginUpdate;
	Items.Clear;
  LoadRoot;
  LoadDrives;
  Items.EndUpdate;
end; //Reload

procedure TLsDirTree10.Expand( Node : TTreeNode );
begin
  inherited Expand( Node );
end; //Expand

procedure TLsDirTree10.Expanding( Sender : TObject; Node : TTreeNode;
  var AllowExpansion : Boolean );
begin
	if Node.GetFirstChild = nil then
  begin
    MakePath( Node );
    Node.HasChildren := false;
    AddSubs( TreeViewPath, Node );
    Node.AlphaSort;
  end;
end; //Expanding

procedure TLsDirTree10.MouseDown( Button : TMouseButton;
	Shift : TShiftState; X, Y : Integer );
var
	vHitTest : THitTests;
	DrvChar : Char;
begin
  TreeViewPath := '';
  if Button = mbLeft then
  begin
    vHitTest := GetHitTestInfoAt( X, Y );
    if ( htOnItem in vHitTest ) or ( htOnIcon in vHitTest ) {v0.30} or (htOnLabel in vHitTest) {/v0.30} then
    begin
      if ( Selected.Level = 0 ) and ( Items[ 0 ].getFirstChild = nil ) then
        LoadDrives
      else
        MakePath( Selected );

      if Selected = Items[ 0 ] then
        FSelectedPath := 'Drives'
      else
        FSelectedPath := TreeViewPath;

      if Selected.Level = 1 then
        if GetDriveType( PChar( FSelectedPath ) ) in
          [ DRIVE_REMOVABLE, DRIVE_CDROM ] then
        begin
          DrvChar := FSelectedPath[ 1 ];
          if not DiskInDrive( DrvChar, 1 ) then
            exit;
        end;
      if Assigned( FFileList ) and ( FSelectedPath <> '' ) then
        FFileList.Directory := FSelectedPath;
    end;
  end;
end; //MouseDown

procedure TLsDirTree10.SetSelectedPath( Value : string );
begin
  if AnsiCompareText( Value, FSelectedPath ) = 0 then
    exit;
  FSelectedPath := Value;
end; //SetSelectedPath

procedure TLsDirTree10.OpenPath( dPath : string );
var
	CurNode : TTreeNode;
	count : Integer;
	TempPath : string;
	CurPath : string;
	FullPath : string;
begin
	if ( dPath = '' ) or ( Length( dPath ) = 1 ) then exit;
	if not DirectoryExists( dPath ) then exit;
	dPath := AddSlash( dPath );
	FullPath := dPath;
	Items.BeginUpdate;
	CurNode := Items[ 0 ];
	if CurNode.getFirstChild = nil then
		LoadDrives;
	if CurNode.Expanded then
		CurNode.Collapse( True );
	CurNode := Items.GetFirstNode;
	while Pos( '\', dPath ) > 0 do
	begin
		count := Pos( '\', dPath );
		tempPath := Copy( dPath, 1, count );
		dPath := Copy( dPath, count + 1, Length( dPath ) );
		CurNode := CurNode.getFirstChild;

		while CurNode <> nil do
		begin
			if CurNode.Level = 1 then
				CurPath := Copy( CurNode.Text, 3, 2 ) + '\'
			else if CurNode.Level > 1 then
				CurPath := CurNode.Text + '\';
			if AnsiCompareText( CurPath, tempPath ) = 0 then
			begin
				CurNode.Selected := True;
				CurNode.Expand( False );
				Break;
			end;
			CurNode := CurNode.GetNext;
			if CurNode = nil then exit;
		end;
	end;
	Items.EndUpdate;
	if AnsiCompareText( FSelectedPath, FullPath ) <> 0 then
	begin
		FullPath := AddSlash( FullPath );
		FSelectedPath := FullPath;
	end;
end; //OpenPath

{**
procedure TLsDirTree10.CNNotify( var Message : tWMNotify );
var
	node : TTreeNode;
begin
	if (message.nmhdr.code = TVN_SELCHANGED then
	begin
		Node := Selected;
		if not Assigned(node) then exit;
		if (Node = Items[0]) then
			FSelectedPath := 'Drives'
		else
			FSelectedPath := TreeViewPath;

		if Assigned(FFileList) and (FSelectedPath <> '') then
			FFileList.Directory := FSelectedPath;
	end;
	inherited;
end; //CNNotify
**}

procedure TLsDirTree10.KeyDown( var Key : Word; Shift : TShiftState );
var
  DrvChar : Char;
begin
  if ( key = VK_RETURN ) then
  begin
    if Selected = nil then
      exit;
    if ( Selected.Level = 0 ) and ( Items[ 0 ].getFirstChild = nil ) then
      LoadDrives
    else
      MakePath( Selected );

    if ( Selected.Level = 0 ) then
      FSelectedPath := 'Drives'
    else
      FSelectedPath := TreeViewPath;

    if Selected.Level = 1 then
      if GetDriveType( PChar( FSelectedPath ) ) in
        [ DRIVE_REMOVABLE, DRIVE_CDROM ] then
      begin
        DrvChar := FSelectedPath[ 1 ];
        if not DiskInDrive( DrvChar, 1 ) then
          exit;
      end;
    if Assigned( FFileList ) and ( FSelectedPath <> '' ) then
      FFileList.Directory := FSelectedPath;
  end; //VK_RETURN
  inherited;
end; //KeyDown

function TLsDirTree10.GetPathFromNode( Node : TTreeNode ) : string;
begin
	Result := '';
	if Node = nil then exit;
	if Assigned( Node ) then
	begin
		MakePath( Node );
		Result := TreeViewPath;
	end;
end; //GetPathFromNode

function TLsDirTree10.CanEdit( Node : TTreeNode ) : Boolean;
begin
  Result := False;
	if ( Assigned( Node.Parent ) ) and ( Node.Level > 1 ) and
    ( not ReadOnly ) then
    Result := inherited CanEdit( Node );
end; //CanEdit

procedure TLsDirTree10.Edit( const Item : TTVItem );
var
  OldDirName : string;
  NewDirName : string;
  Aborted : Boolean;
  OldCur : TCursor;
  Rslt : Boolean;
  SelNode : TTreeNode;
	PrevNode : TTreeNode;

  function GetNodeFromItem( Item : TTVItem ) : TTreeNode;
	begin
		with Item do
      if ( State and TVIF_PARAM ) <> 0 then
        Result := Pointer( lParam )
      else
        Result := Items.GetNode( hItem );
  end; //GetNodeFromItem

begin
  SelNode := GetNodeFromItem( Item );
	PrevNode := SelNode.Parent;
  if not Assigned( SelNode ) then exit;
  if ( SelNode = Items[ 0 ] ) or ( SelNode.Level = 1 ) then
    exit;

  if ( Length( Item.pszText ) = 0 )
    or ( StrContains( InvalidDosChars, Item.pszText ) ) then
  begin
    MessageBeep( MB_ICONHAND );
    if ( Length( Item.pszText ) > 0 ) then
			MessageDlg( 'Error - Invalid Directory Name' + #13 +
        Item.pszText, mtError, [ mbOK ], 0 );
    Exit;
	end;
	if SelNode <> nil then
    OldDirName := GetPathFromNode( SelNode );
  if OldDirName = '' then exit;
  OldCur := Screen.Cursor;
	Screen.Cursor := crHourGlass;
	try
		Aborted := False;
		OldDirName := DelSlash( OldDirName );
		NewDirName := ExtractFilePath( OldDirName ) + Item.pszText;

		if not FIsNewFolder then
		begin
			if MessageDlg( 'Do you want to rename the selected folder' + #13 + #13 +
				'    From  : ' + ExtractFileName( OldDirName ) + #13 +
				'    To     : ' + ExtractFileName( NewDirName ), mtConfirmation,
				[ mbYes, mbNo ], 0 ) = mrNo then
				exit;
		end;

		Rslt := DoSHFileOp( Parent.Handle, FO_RENAME, OldDirName,
			NewDirName, Aborted );

		if Rslt then
		begin
			inherited Edit( Item );
			Selected := PrevNode;
			if Assigned( FFileList ) then
			begin
				FFileList.Directory := GetPathFromNode( Selected );
			end;
		end;
	finally
		Screen.Cursor := OldCur;
		FIsNewFolder := False;
	end;
end; //Edit

function TLsDirTree10.AddNewNode( ParentNode : TTreeNode;
	NodeName : string ) : Boolean;
var
	Path : string;
	Dir : string;
	NewNode : TTreeNode;
begin
	Result := False;
	if ParentNode = nil then
		ParentNode := Selected;
	if ParentNode.Level = 0 then
	begin
		ShowMessage( 'ERROR - Can''t add drives' );
		exit;
	end;

	if NodeName = '' then
	begin
		NodeName := 'New Folder';
		FIsNewFolder := True;
	end;
	try
		Path := GetPathFromNode( ParentNode );
		if Path = '' then exit;
		Path := AddSlash( Path );
		Dir := Path + NodeName;
		Dir := AddNullToStr( Dir );

		if StrContains( InvalidDosChars, NodeName ) then
		begin
			MessageBeep( MB_ICONHAND );
			ShowMessage( 'ERROR - Folder Name contains invalid characters' );
			exit;
		end;
		Items.BeginUpdate;

		Result := CreateDirectory( PChar( Dir ), nil );

		if Result then
		begin
			ReLoad;
			Dir := AddSlash( Dir );
			OpenPath( Dir );
			NewNode := Selected;
			if ( NewNode <> nil ) and ( NodeName = 'New Folder' ) then
				NewNode.EditText;
		end;
	finally
		Items.EndUpdate;
	end;
end; //AddNewNode


function TLsDirTree10.DeleteNode( Node : TTreeNode ) : Boolean;
var
	DelDir : string;
	DelPath : string;
	PrevNode : TTreeNode;
	oldCur : TCursor;
	Aborted : Boolean;
begin
	Result := False;
	Aborted := True;
	PrevNode := Node.Parent; //.GetPrevVisible;
	if ( Assigned( Node ) ) and ( Node.Level > 1 ) then
	begin
		oldCur := Screen.Cursor;
		Screen.Cursor := crHourGlass;
		if Selected <> nil then
			DelDir := GetPathFromNode( Selected );
		if DelDir = '' then exit;
		if not DirectoryExists( Deldir ) then
		begin
			MessageBeep( MB_ICONHAND );
			ShowMessage( 'ERROR - ' + DelDir + #13 +
				'                not found' );
			Screen.Cursor := oldCur;
			exit;
		end;
		DelDir := DelSlash( Deldir );
		DelPath := ExtractFilePath( DelDir );
		//		MessageBeep(MB_ICONHAND);
		Result := DoSHFileOp( Parent.Handle, FO_DELETE, DelDir, '', Aborted );
		if Result then
		begin
			if Assigned( PrevNode ) then
				Selected := PrevNode;
			Node.Delete;
			if Assigned( FFileList ) then
				FFileList.Directory := GetPathFromNode( Selected );
		end;
		Screen.Cursor := oldCur;
	end;
end; //DeleteNode

procedure TLsDirTree10.SetFileList( Value : TLsFileListView26 );
begin
	if FFileList <> Value then
		FFileList := Value;
	if ( Assigned( FFileList ) ) and ( FSelectedPath <> '' ) then
		FFileList.Directory := FSelectedPath;
end; //SetFileList

procedure TLsDirTree10.SetPopUpMenuEnabled( Value : Boolean );
begin
	if Value <> FPopUpMenuEnabled then
	begin
		FPopUpMenuEnabled := Value;
		if FPopUpMenuEnabled then
			PopupMenu := FPopupMenu
		else
			PopupMenu := nil;
	end;
end; //SetPopUpMenuEnabled


{ ====== TLsDirTreePopUp10 ====== }

constructor TLsDirTreePopUp10.Create( AOwner : TComponent );
begin
	inherited Create( AOwner );
end; // Create

destructor TLsDirTreePopUp10.Destroy;
begin
	inherited Destroy;
end; // Destroy

function TLsDirTreePopUp10.AddNewItem( const aCaption : string;
	aShortCut : TShortCut; aChecked, aEnabled : Boolean;
	aGroup : integer; aOnClick : TNotifyEvent;
	hCtx : word; const aName : string ) : TMenuItem;
begin
	Result := NewItem( aCaption, aShortCut, aChecked, aEnabled,
		aOnClick, hCtx, aName );
end; // AddNewItem

procedure TLsDirTreePopUp10.SetDirTree( Value : TLsDirTree10 );
begin
	FDirTree := Value;
end; // SetDirTree

procedure TLsDirTreePopUp10.BuildItems;
begin
	Items.Add( AddNewItem( '&New Folder', 0, False, True, 0,
		ItemOnClick, 0, 'AddNode' ) );
	Items.Add( AddNewItem( '&Rename Folder', 0, False, True, 0,
		ItemOnClick, 0, 'EditNode' ) );
	Items.Add( AddNewItem( '&Delete Folder', 0, False, True, 0,
		ItemOnClick, 0, 'DelNode' ) );
end; // BuildItems

procedure TLsDirTreePopUp10.ItemOnClick( Sender : TObject );
var
	Node : TTreeNode;
begin
	if TMenuItem( Sender ).Name = 'AddNode' then
		FDirTree.AddNewNode( FDirTree.Selected, '' )
	else if TMenuItem( Sender ).Name = 'EditNode' then
		FDirTree.Selected.EditText
	else if TMenuItem( Sender ).Name = 'DelNode' then
	begin
		Node := FDirTree.Selected;
		if Assigned( Node ) then
			FDirTree.DeleteNode( Node );
	end;
end; // ItemOnClick

procedure TLsDirTreePopUp10.PopUp( X, Y : integer );
begin
	inherited Popup( X + 10, Y + 10 );
end; // PopUp

/////End of TLsDirTree10/////


{************************************************************************}
{                        LsFileListView26                                }
{************************************************************************}

constructor TLsFileListView26.Create( AOwner : TComponent );
begin
	inherited Create( AOwner );
	Createimages;
	FSelectedFiles := TStringList.Create;
	MultiSelect := True;
	ReadOnly := False;
	FDateFormat := [ dfMDY ];
	ShortDateFormat := 'mm/dd/yyyy';
	LongTimeFormat := 'hh:nn';
	HideSelection := False;

	ViewStyle := vsReport;
	FMask := DefaultMask;
	FSortForward := True;
	FSortColumn := 0;
	OnCompare := CompareFiles;
	OnColumnClick := ColumnClick;

	SetColumnWidth( 160, 90, 90, 100, 40 );
	ShowColumnHeaders := True;
	FShowFolders := True;
	FDblClickEnabled := True;

	FPopupMenu := TLsFileListViewPopUp26.Create( Self );
	FPopupMenu.BuildItems;
	FPopupMenu.AutoPopup := True;
	FPopupMenu.FFileListView := Self;
	PopupMenu := FPopupMenu;
	FPopUpMenuEnabled := True;
	FFileType := [ ftReadOnly, ftHidden, ftSystem, ftArchive ];

	FDirectory := 'Drives';
end; // Create

destructor TLsFileListView26.Destroy;
begin
	LargeImages.Free;
	SmallImages.Free;
	FPopupMenu.Free;
	FSelectedFiles.Free;
	inherited Destroy;
end; // Destroy

procedure TLsFileListView26.CreateWnd;
begin
	inherited CreateWnd;
	Font.Size := 8;
	Font.Name := 'MS Sans Serif';
	if not ( csLoading in ComponentState ) then
		CreateFileColumns;
end; // CreateWnd

procedure TLsFileListView26.Loaded;
begin
	inherited Loaded;
	CreateFileColumns;
end; // Loaded

function TLsFileListView26.GetFreeSpace : Integer;
begin
	Result := GetFreeDiskSize( Copy( FDirectory, 1, 1 ) + ':\' );
end; // GetFreeSpace

function TLsFileListView26.GetSelectedNum : Integer;
begin
	Result := SelCount;
	if Result = 0 then Result := Items.Count;
end; // GetSelectedNum

function TLsFileListView26.GetSelectedSize : Integer;
var
  i, FSize : UInt;
  FName : string;
  win32FD : TWin32FindData;
  hFindFile : THandle;
begin
  Result := 0;
	FSize := 0;
  hFindFile := 0;
  if SelCount = 0 then exit;
  for i := 0 to Items.Count - 1 do
	begin
    if Items[ i ].selected then
    begin
      FName := ExtractFileName( Items[ i ].SubItems[ 4 ] + #0 );
      hFindFile := FindFirstFile( pChar( FName ), win32FD );
      if hFindFile <> INVALID_HANDLE_VALUE then
        FSize := FSize + ( ( win32FD.nFileSizeHigh * MAXDWORD ) +
          win32FD.nFileSizeLow );
    end;
  end;
  Windows.FindClose( hFindFile );
	Result := FSize;
end; // GetSelectedSize

function TLsFileListView26.GetDirectory : string;
begin
  Result := FDirectory;
end; // GetDirectory

procedure TLsFileListView26.SetDirectory( NewDir : string );
begin
  if AnsiCompareText( NewDir, FDirectory ) = 0 then exit;
  if ( UpperCase( NewDir ) = 'DRIVES' ) then
	begin
    FDirectory := NewDir;
    UpdateFileList;
  end
  else
  begin
    if not DirectoryExists( NewDir ) then exit;
		NewDir := AddSlash( NewDir );
    SetCurrentDir( NewDir );
    FDirectory := NewDir;
    UpdateFileList;
	end;
end; // SetDirectory

procedure TLsFileListView26.SetDirTreeCombo( val : TLsDirTreeCombo26 );
begin
  if FDirTreeCombo = Val then
    exit
  else
  begin
    if Assigned( FDirTreeCombo ) then
      FDirTreeCombo.FileList := nil;
    FDirTreeCombo := Val;
	end;
	if Assigned( FDirTreeCombo ) then
    FDirTreeCombo.FileList := self;
end; // SetDirTreeCombo

procedure TLsFileListView26.SetDirTree( VaL : TLsDirTree10 );
begin
  if FDirTree = Val then
    exit
  else
  begin
    if Assigned( FDirTree ) then
      FDirTree.FileList := nil;
    FDirTree := Val;
	end;
	if Assigned( FDirTree ) then
		FDirTree.FileList := self;
end; // SetDirTree


procedure TLsFileListView26.Notification( AComponent : TComponent;
  Operation : TOperation );
begin
	inherited Notification( AComponent, Operation );
  if ( Operation = opRemove ) and ( AComponent = FDirTree ) then
    FDirTree := nil;
  if ( Operation = opRemove ) and ( AComponent = FDirTreeCombo ) then
    FDirTreeCombo := nil;
end; // Notification

procedure TLsFileListView26.SetMask( const NewMasks : string );
begin
  if FMask <> NewMasks then
  begin
    FMask := NewMasks;
		UpdateFileList;
  end;
end; // SetMask

function TLsFileListView26.GetSelectedItem : string;
begin
  Result := FSelectedItem;
end; // GetSelectedItem

procedure TLsFileListView26.SetSelectedItem( NewItem : string );
begin
	if FSelectedItem = NewItem then exit;
  FSelectedItem := NewItem;
end; // SetSelectedItem

procedure TLsFileListView26.SetFileType( NewFileType : TFileType );
begin
	if NewFileType <> FFileType then
  begin
    FFileType := NewFileType;
    UpdateFileList;
  end;
end; // SetFileType

procedure TLsFileListView26.SetDateFormat( NewFmt : TDateFormat );
begin
  FDateFormat := NewFmt;
  if FDateFormat = [ dfMDY ] then
    ShortDateFormat := 'mm/dd/yyyy'
  else if FDateFormat = [ dfDMY ] then
    ShortDateFormat := 'dd/mm/yyyy'
	else if FDateFormat = [ dfYMD ] then
    ShortDateFormat := 'yyyy/mm/dd';
  UpdateFileList;
end; // SetDateFormat

procedure TLsFileListView26.SetShowFolders( Value : Boolean );
begin
  if FShowFolders = Value then
    exit;
  FShowFolders := Value;
  UpdateFileList;
end; // SetShowFolders

procedure TLsFileListView26.Createimages;
var
  sfi : TSHFileInfo;
begin
  if not Assigned( LargeImages ) then
  begin
    Largeimages := TImageList.Create( self );
		LargeImages.Handle := SHGetFileInfo( '', 0, sfi, SizeOf( TSHFileInfo ),
      SHGFI_SYSICONINDEX or SHGFI_LARGEICON );
    LargeImages.ShareImages := TRUE;
	end;
  if not Assigned( SmallImages ) then
  begin
		Smallimages := TImageList.Create( Self );
    Smallimages.Handle := SHGetFileInfo( '', 0, sfi, SizeOf( TSHFileInfo ),
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON );
    Smallimages.ShareImages := TRUE;
  end;
end; // CreateImages

procedure TLsFileListView26.SetColumnWidth( Col_Name, Col_Size, Col_Type,
  Col_Mod, Col_Attr : integer );
begin
  with FColumnWidths do
	begin
    cwName := Col_Name;
    cwSize := Col_Size;
    cwType := Col_Type;
    cwMod := Col_Mod;
    cwAttr := Col_Attr;
  end;
end; // SetColumnWidth

procedure TLsFileListView26.CreateDriveColumns;
begin
  Columns.Clear;
	with Columns.Add do
  begin
    Caption := 'Name';
    Width := FColumnWidths.cwName;
    Alignment := taLeftJustify;
	end;
  with Columns.Add do
  begin
    Caption := 'Type';
    Width := FColumnWidths.cwMod;
    Alignment := taLeftJustify;
  end;
  with Columns.Add do
  begin
    Caption := 'Disk Size';
    Width := FColumnWidths.cwSize;
    Alignment := taRightJustify;
  end;
  with Columns.Add do
  begin
		Caption := 'Free Space';
    Width := FColumnWidths.cwType;
		Alignment := taRightJustify;
	end;
  with Columns.Add do
  begin
    Caption := 'Attributes';
    Width := FColumnWidths.cwAttr;
    Alignment := taLeftJustify;
  end;
end; // CreateDriveColumns

procedure TLsFileListView26.CreateFileColumns;
begin
  Columns.Clear;
  with Columns.Add do
  begin
    Caption := 'Name';
    Width := FColumnWidths.cwName; //default=160;
		Alignment := taLeftJustify;
  end;
  with Columns.Add do
  begin
		Caption := 'Size(Bytes)';
    Width := FColumnWidths.cwSize; //default=90;
    Alignment := taRightJustify;
	end;
  with Columns.Add do
  begin
    Caption := 'Type';
    Width := FColumnWidths.cwType; //default=90;
    Alignment := taLeftJustify;
  end;
  with Columns.Add do
  begin
    Caption := 'Modified';
		Width := FColumnWidths.cwMod; //default=100;
    Alignment := taLeftJustify;
  end;
  with Columns.Add do
  begin
    Caption := 'Attributes';
    Width := FColumnWidths.cwAttr; //default=40;
    Alignment := taLeftJustify;
  end;
end; // CreateFileColumns

procedure TLsFileListView26.ColumnClick( Sender : TObject;
  Column : TListColumn );
var
  required_column : integer;
begin
  required_column := Column.Index;
	if required_column = FSortColumn then
    FSortForward := not FSortForward
  else
  begin
    FSortColumn := required_column;
    FSortForward := True;
  end;
  SortType := stData;
  SortType := stNone;
end; // ColumnClick

procedure TLsFileListView26.CompareFiles( Sender : TObject; Item1,
  Item2 : TListItem; Data : Integer; var Compare : Integer );
var
  Caption1,
    Caption2 : string;
	size1,
		size2 : integer;
  date1,
		date2 : TDateTime;
  result : integer;
begin
  Result := 0;
  // To force Directories to be displayed before Files
  if ( Item1.SubItems[ 5 ] = 'dir' ) and ( Item2.SubItems[ 5 ] <> 'dir' ) then
    Result := -1
  else if ( Item1.SubItems[ 5 ] <> 'dir' ) and ( Item2.SubItems[ 5 ] = 'dir' )
    then
    Result := 1
      // Compare files
  else
  begin
    // sort on file name
    if FSortColumn = 0 then
		begin
      Caption1 := AnsiUpperCase( Item1.Caption );
      Caption2 := AnsiUpperCase( Item2.Caption );
      if Caption1 > Caption2 then
        Result := 1
			else if Caption1 < Caption2 then
        Result := -1;
    end
			// sort on file size
    else if FSortColumn = 1 then
    begin
      size1 := StrToInt( Trim( Item1.SubItems.Strings[ 0 ] ) );
      size2 := StrToInt( Trim( Item2.SubItems.Strings[ 0 ] ) );
      if Size1 > Size2 then
        Result := 1
      else if Size1 < Size2 then
        Result := -1;
		end
      // sort on files' modified date
    else if FSortColumn = 3 then
    begin
      date1 := StrToDateTime( Item1.SubItems.Strings[ 2 ] );
      date2 := StrToDateTime( Item2.SubItems.Strings[ 2 ] );
      result := Round( 1E5 * ( date1 - date2 ) );
    end
    else
    begin
      result := CompareText( Item1.SubItems.Strings[ FSortColumn - 1 ],
				Item2.SubItems.Strings[ FSortColumn - 1 ] );
    end;
  end; // else
	if FSortForward then
    Compare := -result
  else
		Compare := result;
end; // CompareFiles

procedure TLsFileListView26.Keydown( var Key : Word; Shift : TShiftState );
begin
	if Shift = [ ssCtrl ] then
	begin
		case Key of
			$43 :  if Selected <> nil then CutCopy( 0 );     // (VK_C)Copy
			$58 :  if Selected <> nil then CutCopy( 2 );     // (VK_X)Cut
			$56 :  if FSelectedFiles.Count <> 0 then Paste;  // (VK_V)Paste
			$4F :  if Selected <> nil then OpenItem;         // (VK_O)OpenItem
			$46 :  if Selected <> nil then ViewFile;         // (VK_F)View file
			$4E :  if AnsiCompareText( FDirectory, 'DRIVES' ) <> 0 then
							 NewFolder;                              // (VK_N)New Folder
		end;
	end
	else if ( Shift = [ ] ) and ( not isEditing ) then
	begin
		case Key of
			VK_UP     : Click;                               // UpArrow
			VK_DOWN   : Click;                               // DownArrow
			VK_DELETE : if Selected <> nil then DeleteItems; // Delete File
			VK_RETURN : if Selected <> nil then OpenItem;    // Open
			VK_BACK   : OneLevelUp;                          // Previous Directory
			VK_F2     : if Selected <> nil then RenameFile;  // ReName File
			VK_F3     : FindFile;
			VK_F5     : UpdateFileList;                      //52 Refresh LsFileListView

			VK_F4 :                                          //52 Display TreeView
				begin
					if not Assigned(DirTreeCombo) then exit;
					DirTreeCombo.BtnClick( Self );
					if DirTreeCombo.Tree.Visible then
						DirTreeCombo.Tree.SetFocus;
				end;
			VK_ESCAPE :                                      //52 Close TreeView
				begin
					if not Assigned(DirTreeCombo) then exit;
					if DirTreeCombo.Tree.Enabled = True then
					begin
						DirTreeCombo.Tree.Enabled := False;
						DirTreeCombo.Tree.Visible := False;
						DirTreeCombo.SendToBack;
					end;
				end;
		end; // case
	end; // else
	inherited KeyDown( Key, Shift );
end; // KeyDown

procedure TLsFileListView26.UpdateFileList;
var
	oldCur : TCursor;
	MaskPtr : PChar;
	AttrIndex : TFileAttr;
	Ptr : PChar;
	DirAttr,
	 FileAttr : DWORD;
	FName,
	 CurPath : string;
const
	dwFileAttr : array[ TFileAttr ] of DWord = ( FILE_ATTRIBUTE_READONLY,
		FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_SYSTEM,
		FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL );
begin
	Items.beginUpdate;
	Items.Clear;
	OldCur := Screen.Cursor;
	Screen.Cursor := crHourGlass;
	FDirectorySize := 0;
	try
		// Add Drives to LsFileListView26
		if UpperCase( FDirectory ) = 'DRIVES' then
		begin
			CreateDriveColumns;
			AddDrives
		end
		else
		begin
			// Add directories to LsFileListView26
			CreateFileColumns;
			FileAttr := 0;
			for AttrIndex := ftReadOnly to ftNormal do
				if AttrIndex in FileType then
					FileAttr := FileAttr or dwFileAttr[ AttrIndex ];
			DirAttr := FileAttr or FILE_ATTRIBUTE_DIRECTORY;
			CurPath := AddSlash( FDirectory );
			FName := CurPath + '*.*';
			if ShowFolders then
				AddFiles( FName, DirAttr );

			// Add files to LsFileListView26
			MaskPtr := PChar( FMask );
			while MaskPtr <> nil do
			begin
				Ptr := StrScan( MaskPtr, ';' );
				if Ptr <> nil then
					Ptr^ := #0;
				AddFiles( ( CurPath + StrPas( MaskPtr ) ), FileAttr );
				if Ptr <> nil then
				begin
					Ptr^ := ';';
					inc( Ptr );
				end;
				MaskPtr := Ptr;
			end; // while MaskPtr ...
		end; // else  FDirectory <> 'Drives'
	finally
		FSortForward := True;
		ColumnClick( Self, Columns[ 0 ] );
	end; // try
	Items.EndUpdate;
	Screen.Cursor := oldCur;
	if ( Items.Count > 0 ) and ( SelCount = 0 ) then
		ItemFocused := Items[ 0 ];
	Application.ProcessMessages;
end; // UpdateFileList

procedure TLsFileListView26.AddDrives;
var
	Drives : set of 0..25;
  sfi : TSHFileInfo;
  NewItem : TListItem;
  i : Integer;
	DiskType : Integer;
  DiskSize,
    FreeSize : Integer;
	Drv : Char;
  DrvName : string;

  function GetDriveTypeStr( Root : string ) : string;
  var
    DrvType : Integer;
  begin
    DrvType := GetDriveType( PChar( Root ) );
    case DrvType of
      0 : Result := 'Unknown';
      1 : Result := 'Not exist';
      DRIVE_REMOVABLE : Result := 'Removable Disk';
      DRIVE_FIXED : Result := 'Fixed Disk';
      DRIVE_REMOTE : Result := 'Network Disk';
			DRIVE_CDROM : Result := 'CD-ROM Disk';
      DRIVE_RAMDISK : Result := 'RAM Disk';
		end;
  end; // GetDriveTypeStr

begin
  Integer( Drives ) := GetLogicalDrives;
  for i := 0 to 25 do
    if ( i in Drives ) then
		begin
      Drv := Char( i + Ord( 'A' ) );
      NewItem := Items.Add;
      try
        SHGetFileInfo( PChar( Drv + ':\' ), 0, sfi, SizeOf( sfi ),
          SHGFI_SYSICONINDEX or SHGFI_DISPLAYNAME or SHGFI_TYPENAME );
        if SmallImages <> nil then
          NewItem.ImageIndex := sfi.Iicon;
				DrvName := copy( sfi.szDisplayName, 1,
          ( Pos( '(', sfi.szDisplayName ) - 1 ) );
        NewItem.Caption := ' (' + Drv + ':)  ' + DrvName;
        DiskType := GetDriveType( PChar( Drv + ':\' ) );
        NewItem.SubItems.Add( GetDriveTypeStr( Drv + ':\' ) );

        if ( DiskType <> DRIVE_REMOVABLE ) and ( DiskType <> DRIVE_CDROM ) then
        begin
					DiskSize := GetDiskSize( Drv + ':\' );
          FreeSize := GetFreeDiskSize( Drv + ':\' );
        end
        else
        begin
          DiskSize := 0;
          FreeSize := 0;
				end;

				if DiskSize > 0 then
					NewItem.SubItems.Add( FormatFloat( '###,###,### Mb',
																DiskSize div 1000 ) )
				else
					NewItem.SubItems.Add( '0 Mb' );

				if FreeSize > 0 then
					NewItem.SubItems.Add( FormatFloat( '###,###,### Mb',
																FreeSize div 1000 ) )
				else
					NewItem.SubItems.Add( '0 Mb' );
				NewItem.SubItems.Add( '' );
				NewItem.SubItems.Add( Drv + ':\' );
				NewItem.SubItems.Add( 'drv' );
			except
				Items.Delete( NewItem.Index );
			end;
		end;
end; // AddDrives

function TLsFileListView26.AddFiles( FileMask : string; Attr : DWord ) :
	Boolean;
var
	sfi : TSHFileInfo;
	attributes,
		CurPath,
		FDate,
		FName,
		FileName,
		FileDir : string;
	FSize : Integer;
	hFindFile : THandle;
	Win32FD : TWin32FindData;

	function AttrStr( Attr : integer ) : string;
	begin
		Result := '';
		if ( FILE_ATTRIBUTE_DIRECTORY and Attr ) > 0 then Result := Result + '';
		if ( FILE_ATTRIBUTE_ARCHIVE and Attr ) > 0 then Result := Result + 'A';
		if ( FILE_ATTRIBUTE_READONLY and Attr ) > 0 then Result := Result + 'R';
		if ( FILE_ATTRIBUTE_HIDDEN and Attr ) > 0 then Result := Result + 'H';
		if ( FILE_ATTRIBUTE_SYSTEM and Attr ) > 0 then Result := Result + 'S';
	end;

begin
	Result := False;
	//  if not SetCurrentDir(FDirectory) then exit;
	CurPath := AddSlash( FDirectory );
	hFindFile := FindFirstFile( PChar( FileMask ), Win32FD );
  if hFindFile <> INVALID_HANDLE_VALUE then
  try
		repeat
      with Win32FD do
      begin // Depending on attribute values of FileType property
        if ( ( Attr and FILE_ATTRIBUTE_DIRECTORY ) =
          ( dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) ) and
          ( ( Attr and FILE_ATTRIBUTE_READONLY ) >=
          ( dwFileAttributes and FILE_ATTRIBUTE_READONLY ) ) and
          ( ( Attr and FILE_ATTRIBUTE_HIDDEN ) >=
          ( dwFileAttributes and FILE_ATTRIBUTE_HIDDEN ) ) and
					( ( Attr and FILE_ATTRIBUTE_SYSTEM ) >=
          ( dwFileAttributes and FILE_ATTRIBUTE_SYSTEM ) ) then
        begin
          if ( dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) > 0 then
            FileDir := 'dir'
          else
            FileDir := 'file';

					FName := StrPas( Win32FD.cFilename );
          FileName := CurPath + FName;
          if ( FName = '.' ) or ( FName = '..' ) then continue;

          SHGetFileInfo( PChar( FileName ), 0, sfi, SizeOf( sfi ),
            SHGFI_TYPENAME or SHGFI_SYSICONINDEX or SHGFI_DISPLAYNAME );

          FSize := ( nFileSizeHigh * MAXDWORD ) + nFileSizeLow;
          FDate := FileTimeToDateTimeStr( ftLastWriteTime );
          Attributes := AttrStr( dwFileAttributes );

          with Items.Add do
          begin
						Caption := FName;                   // add Name
						if SmallImages <> nil then
							ImageIndex := sfi.iIcon;          // add icon
						SubItems.Add( IntToStr( FSize ) );  // SubItems[0]-Size
						SubItems.Add( ( sfi.szTypeName ) ); // SubItems[1]-TypeName
						SubItems.Add( FDate );              // SubItems[2]-DateTime
						SubItems.Add( Attributes );         // SubItems[3]-Attributes
						SubItems.Add( FileName );           // SubItems[4]-Path+FileName
						SubItems.Add( FileDir );            // SubItems[5]-dir or file
					end; // with Items ...

					FDirectorySize := FDirectorySize + FSize;
					Result := True;
				end; // Attr ...
			end; // with Win32FD
		until not FindNextFile( hFindFile, Win32FD );
	finally
		windows.FindClose( hFindFile );
	end; // try
end; // AddFiles

procedure TLsFileListView26.OneLevelUp;
var
	NewDir : string;
begin
	if UpperCase( Directory ) = 'DRIVES' then
		exit;
	FDirectory := AddSlash( FDirectory );
	if ( FDirectory[ Length( FDirectory ) - 1 ] = ':' ) then
	begin
		if ( FDirTreeCombo <> nil ) then
			FDirTreeCombo.OpenPath( FDirTreeCombo.Tree.Items[ 0 ].Text );
		if ( FDirTree <> nil ) then
			FDirTree.OpenPath( FDirTree.Items[ 0 ].Text );
		SetDirectory( 'Drives' );
	end
	else
	begin
		FDirectory := Copy( FDirectory, 1, Length( FDirectory ) - 1 );
		NewDir := ExtractFilePath( FDirectory );
		SetDirectory( NewDir );
		if FDirTree <> nil then
			FDirTree.OpenPath( NewDir );
		if FDirTreeCombo <> nil then
			FDirTreeCombo.OpenPath( NewDir );
	end;
end; // OneLevelUp

procedure TLsFileListView26.Click;
begin
	if Selected <> nil then
		SetSelectedItem( Selected.SubItems[ 4 ] );
	inherited Click;
end; // Click

procedure TLsFileListView26.SetDblClickEnabled( Value : Boolean );
begin
	if Value <> FDblClickEnabled then
		FDblClickEnabled := Value;
end; // SetDblClickEnabled

procedure TLsFileListView26.DblClick;
begin
	if not FDblClickEnabled then
		exit;
	inherited DblClick;
	OpenItem;
end; // DblClick

procedure TLsFileListView26.SetPopUpMenuEnabled( Value : Boolean );
begin
	if Value <> FPopUpMenuEnabled then
	begin
		FPopUpMenuEnabled := Value;
		if FPopUpMenuEnabled then
			PopupMenu := FPopupMenu
		else
			PopupMenu := nil;
  end;
end; // SetPopUpMenuEnabled


///// FileOperations /////

function TLsFileListView26.CanEdit( Item : TListItem ) : Boolean;
begin
  Result := False;
	if not ReadOnly then
  begin
		Result := inherited CanEdit( Item );
  end;
end; // CanEdit

procedure TLsFileListView26.Edit( const Item : TLVItem );
var
  Path,
    newFName,
    DirOrFile : string;
  Abort : Boolean;
  OldCur : TCursor;
begin
  inherited Edit( Item );
  OldCur := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  Items.BeginUpdate;
  try
		if Selected <> nil then
    begin
      Path := ExtractFilePath( OldFName );
      DirOrFile := Selected.SubItems[ 5 ];
			newFName := AddNullToStr( Path + Selected.Caption );
      if AnsiCompareText( OldFName, newFName ) = 0 then exit;

      if not FileDirExist( newFName ) then
        DoSHFileOp( Parent.Handle, FO_RENAME, OldFName, newFName, Abort );

      UpdateFileList;

      if AnsiCompareText( DirOrFile, 'DIR' ) = 0 then
      begin
        if Assigned( FDirTree ) then
        begin
          FDirTree.Reload;
					FDirTree.OpenPath( Path );
        end
        else if Assigned( FDirTreeCombo ) then
        begin
          FDirTreeCombo.ResetTreeView;
          FDirTreeCombo.OpenPath( Path );
        end;
      end;
    end;
  finally
		Items.EndUpdate;
    Screen.Cursor := oldCur;
  end;
end; // Edit

procedure TLsFileListView26.NewFolder;
var
	NewFolder : string;
  NewDir : string;
begin
  if ReadOnly then
  begin
    ShowMessage( 'It''s ReadOnly! ' );
		exit;
  end;

  NewFolder := '';
  NewDir := '';
  if not InputQuery( 'Add New Folder', 'Enter new folder name', NewFolder )
    then
    exit;
  NewDir := SlashSep( FDirectory, NewFolder );
  NewDir := AddNullToStr( NewDir );

	if FileDirExist( NewDir ) then exit;

  CreateDir( NewDir );
  UpdateFileList;

  if Assigned( DirTreeCombo ) then
  begin
    FDirTreeCombo.ResetTreeView;
    FDirTreeCombo.OpenPath( NewDir );
  end
  else if Assigned( FDirTree ) then
  begin
		FDirTree.Reload;
    FDirTree.OpenPath( NewDir );
  end;
end; // NewFolder

procedure TLsFileListView26.RenameFile;
var
  SelItem : TListItem;
begin
  if Selected = nil then exit;
	if ReadOnly or ( UpperCase( Selected.SubItems[ 3 ] ) = 'R' ) then
  begin
    ShowMessage( 'It''s ReadOnly' );
    exit;
  end;
  OldFName := AddNullToStr( Selected.SubItems[ 4 ] );
  SelItem := Selected;
  CanEdit( SelItem );
  Selected.EditCaption;
end; // ReNameFile

procedure TLsFileListView26.DeleteItems;
var
	i : integer;
  Abort : Boolean;
  DelFName : string;
  oldCur : TCursor;
begin
  Abort := False;
  oldCur := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  if not SetCurrentDir( FDirectory ) then exit;
  try
		FSelectedFiles.Clear;
    for i := 0 to Items.Count - 1 do
    begin
      if Items[ i ].Selected then
        FSelectedFiles.Add( AddNullToStr( Items[ i ].SubItems[ 4 ] ) ); //60
    end;
		for i := 0 to FSelectedFiles.Count - 1 do
    begin
      DelFName := '';
      DelFName := FSelectedFiles.Strings[ i ];
      DoSHFileOp( Parent.Handle, FileOpMode[ 1 ], DelFName, '', Abort );
    end;
  finally
		UpdateFileList;
    FSelectedFiles.Clear;
    if Assigned( FDirTreeCombo ) then
    begin
      FDirTreeCombo.ResetTreeView;
      FDirTreeCombo.OpenPath( FDirectory );
    end
    else if Assigned( FDirTree ) then
    begin
      FDirTree.Reload;
			FDirTree.OpenPath( FDirectory );
    end;
  end;
  Screen.Cursor := oldCur;
end; // DeleteItems

procedure TLsFileListView26.CutCopy( Mode : integer );
var
  i : integer;
begin
  FOpMode := -1;
  //	FIsDirectory := False;
  FSelectedFiles.Clear;
	for i := 0 to Items.Count - 1 do
  begin
    if Items[ i ].selected then
    begin
			if AnsiCompareText( Items[ i ].SubItems[ 5 ], 'DIR' ) <> 0 then
        FSelectedFiles.Add( AddNullToStr( Items[ i ].SubItems[ 4 ] ) )
      else
        ShowMessage( 'ERROR - Folders can''t be cut or copied ' + #13 +
										 '                in this component' );
		end;
	end;
	FOpMode := Mode;
end; // CutCopy

procedure TLsFileListView26.Paste;
var
	i : integer;
	FSrc,
		FDes,
		DFName : string;
	Abort : Boolean;
	oldCur : TCursor;
begin
	Abort := False;
	oldCur := Screen.Cursor;
	Screen.Cursor := crHourGlass;
	if not SetCurrentDir( FDirectory ) then
		exit;
	if FSelectedFiles.Count = 0 then
	begin
		ShowMessage( 'No file(s) selected' );
		exit;
	end;
	try
		for i := 0 to FSelectedFiles.Count - 1 do
		begin
			FSrc := '';
			FDes := '';
			FSrc := FSelectedFiles.Strings[ i ];
			DFName := ExtractFileName( FSrc );
			FDes := SlashSep( FDirectory, DFName );
			FDes := AddNullToStr( FDes );
			DoSHFileOp( Parent.Handle, FileOpMode[ FOpMode ], FSrc, FDes, Abort );
		end;
	finally
		UpdateFileList;
		FSelectedFiles.Clear;
	end;
	Screen.Cursor := oldCur;
end; // Paste

procedure TLsFileListView26.OpenItem;
var
	sFile,
		sDir : string;
	cDrv : Char;
	oldCur : TCursor;
begin
	if Selected = nil then exit;
	OldCur := Screen.Cursor;
	Screen.Cursor := crHourGlass;
	if ( Selected.SubItems[ 5 ] = 'dir' ) or
		( Selected.SubItems[ 5 ] = 'drv' ) then
	begin
		sDir := Selected.SubItems[ 4 ];
		sDir := AddSlash( sDir );
		if Selected.SubItems[ 5 ] = 'drv' then
			if GetDriveType( PChar( sDir ) ) = DRIVE_REMOVABLE then
			begin
				cDrv := Selected.SubItems[ 4 ][ 1 ];
				if not DiskInDrive( cDrv, 1 ) then
				begin
					Screen.Cursor := OldCur;
					exit;
				end;
			end;
		SetDirectory( sDir );
		if FDirTree <> nil then
			FDirTree.OpenPath( sDir );
		if FDirTreeCombo <> nil then
			FDirTreeCombo.OpenPath( sDir );
	end
	else if Selected.SubItems[ 5 ] = 'file' then
	begin
		sFile := ExtractFileName( Selected.SubItems[ 4 ] );
		sDir := ExtractFilePath( Selected.SubItems[ 4 ] );
		ExecuteFile( 'Open', sFile, '', sDir, SW_SHOW );
	end;
	Screen.Cursor := OldCur;
end; // OpenItem

procedure TLsFileListView26.ViewFile;
var
	i : integer;
	sExt,
		sPath,
		sFName,
		WinDir : string;
begin
	if Selected <> nil then
	begin
		sPath := ExtractFilePath( Selected.SubItems[ 4 ] );
		sPath := AddSlash( sPath );
		sFName := ExtractFileName( Selected.SubItems[ 4 ] );
		sExt := UpperCase( ExtractFileExt( Selected.SubItems[ 4 ] ) );
		SetLength( WinDir, MAX_PATH ); //52
		SetLength( WinDir, GetWindowsDirectory( PChar( WinDir ), MAX_PATH ) ); //52
		WinDir := AddSlash( WinDir );
		for i := Low( FileExt ) to High( FileExt ) do
			if ( i <= 9 ) and ( sExt = FileExt[ i ] ) then
				ExecuteFile( 'Open', WinDir + 'NotePad.exe', sFName, sPath, SW_SHOW )
			else if ( i > 9 ) and ( i <= 12 ) and ( sExt = FileExt[ i ] ) then
				ExecuteFile( 'Open', WinDir + 'Write.exe', sFName, sPath, SW_SHOW )
			else if ( i = 13 ) and ( sExt = FileExt[ i ] ) then
				ExecuteFile( 'Open', WinDir + 'PBrush.exe', sFName, sPath, SW_SHOW );
	end;
end; // ViewFile

procedure TLsFileListView26.FindFile;
begin
	if Focused then
		ExecuteFile( 'Find', Directory, '', '', SW_SHOWNORMAL );
end; // FindFile

procedure TLsFileListView26.FileAttr;
var
	NewAttr,
		OldAttr : word;
	AttrForm : TForm;
	Panel1 : TPanel;
  CbxA,
    CbxR,
    CbxS,
    CbxH : TCheckBox;
  BtnOK,
    BtnCancel : TBitBtn;
  LblFName : TLabel;
begin
	AttrForm := TForm.Create( Application );
  with AttrForm do
	try
    ClientHeight := 172;
    ClientWidth := 266;
    Canvas.Font.Name := 'MS Sens Serif';
    Canvas.Font.Size := 8;
    BorderStyle := bsDialog;
    Caption := 'Set Attributes';
    Position := poScreenCenter;
    LblFName := TLabel.Create( Self );
    with LblFName do
    begin
      Parent := AttrForm;
			Left := 20;
      Top := 12;
      Font.Size := 10;
      Caption := ExtractFileName( Selected.SubItems[ 4 ] );
    end;
		Panel1 := TPanel.Create( Self );
    with Panel1 do
    begin
      Parent := AttrForm;
			Left := 20;
      Top := 34;
      Height := 77;
      Width := 225;
      BevelOuter := bvNone;
      BevelInner := bvLowered;
      CbxR := TCheckBox.Create( Self );
      with CbxR do
      begin
        Parent := Panel1;
        Left := 20;
        Top := 16;
        Caption := 'ReadOnly';
				Checked := False;
			end;
      CbxA := TCheckBox.create( Self );
      with CbxA do
      begin
        Parent := Panel1;
        Left := 20;
        Top := 44;
        Caption := 'Archive';
        Checked := False;
			end;
      CbxH := TCheckBox.Create( Self );
      with CbxH do
      begin
        Parent := Panel1;
        Left := 120;
        Top := 16;
				Caption := 'Hidden';
        Caption := Trim( Caption );
        Checked := False;
      end;
      CbxS := TCheckBox.Create( Self );
      with CbxS do
      begin
				Parent := Panel1;
        Left := 120;
        Top := 44;
        Caption := 'System';
        Caption := Trim( Caption );
        Checked := False;
      end;
    end; // Panel1
    BtnOK := TBitBtn.Create( Self );
		with BtnOK do
		begin
      Parent := AttrForm;
      Top := 128;
      Left := 44;
      Height := 25;
      Width := 75;
      Kind := bkOK;
      ModalResult := mrOK;
    end;
    BtnCancel := TBitBtn.Create( Self );
    with BtnCancel do
    begin
      Parent := AttrForm;
			Top := 128;
      Left := 140;
      Height := 25;
      Width := 75;
			Kind := bkCancel;
      ModalResult := mrCancel;
    end;
    OldAttr := FileGetAttr( Selected.SubItems[ 4 ] );
    CbxR.Checked := OldAttr and faReadOnly = faReadOnly;
		CbxA.Checked := OldAttr and faArchive = faArchive;
    CbxH.Checked := OldAttr and faHidden = faHidden;
    CbxS.Checked := OldAttr and faSysFile = faSysFile;
    ShowModal;
    if ModalResult = mrOK then
    begin
      NewAttr := OldAttr;
      if CbxR.Checked then
        NewAttr := NewAttr or faReadOnly
      else
        NewAttr := NewAttr and not faReadOnly;
      if CbxA.Checked then
				NewAttr := NewAttr or faArchive
      else
				NewAttr := NewAttr and not faArchive;
      if CbxS.Checked then
        NewAttr := NewAttr or faSysFile
      else
        NewAttr := NewAttr and not faSysFile;
      if CbxH.Checked then
        NewAttr := NewAttr or faHidden
      else
        NewAttr := NewAttr and not faHidden;
			if NewAttr <> OldAttr then
        FileSetAttr( Selected.SubItems[ 4 ], NewAttr );
      UpdateFileList;
    end; // mrOK
  finally
    AttrForm.Free;
	end;
end; // FileAttr

procedure TLsFileListView26.SendTo( SubItems : integer );
var
  ADirPath,
    SelPath : string;
  CopyBrd : TRichEdit;
	FNMemo : TMemo;
  AImage : TImage;
  FPath,
    FExt : string;
  i : integer;
  oldCur : TCursor;

  function InputDlg( AValue : string ) : string;
  var
		TDlgForm : TForm;
    Prompt : TLabel;
    Edit : TEdit;
    BtnOk : TBitBtn;
    BtnCancel : TBitBtn;
    BtnBrowse : TBitBtn;
    ButtonTop : Integer;
    ButtonWidth : Integer;
    ButtonHeight : Integer;
    mrBrowse : TModalResult;
  begin
    Result := '';
    mrBrowse := mrNo + 3;
    TDlgForm := TForm.Create( Application );
    with TDlgForm do
    try
      Canvas.Font.Name := 'MS Sans Serif';
			Canvas.Font.Size := 8;
      BorderStyle := bsDialog;
      Caption := 'Send to any folder';
      ClientWidth := 333;
      ClientHeight := 135;
      Position := poScreenCenter;
			Prompt := TLabel.Create( TDlgForm );
      with Prompt do
      begin
        Parent := TDlgForm;
        AutoSize := True;
        Left := 20;
        Top := 12;
        Caption := 'Please enter the send to path';
      end;
      Edit := TEdit.Create( TDlgForm );
      with Edit do
      begin
        Parent := TDlgForm;
        Left := Prompt.Left;
				Top := 32;
        Width := 293;
        MaxLength := 285;
        Text := AValue;
        SelectAll;
      end;
      ButtonTop := 80;
      ButtonWidth := 75;
      ButtonHeight := 25;
      BtnOK := TBitBtn.Create( TDlgForm );
      with BtnOK do
      begin
        Parent := TDlgForm;
        Kind := bkOK;
				Caption := 'OK';
        ModalResult := mrOk;
        Default := True;
        Cancel := True;
        SetBounds( 37, ButtonTop, ButtonWidth, ButtonHeight );
      end;
      BtnCancel := TBitBtn.Create( TDlgForm );
      with BtnCancel do
      begin
				Parent := TDlgForm;
        Kind := bkCancel;
        Caption := 'Cancel';
        ModalResult := mrCancel;
        Cancel := True;
        SetBounds( 129, ButtonTop, ButtonWidth, ButtonHeight );
      end;
      BtnBrowse := TBitBtn.Create( TDlgForm );
			with BtnBrowse do
			begin
        Parent := TDlgForm;
        Kind := bkHelp;
        Caption := 'Browse';
        Cancel := False;
        ModalResult := mrBrowse;
        SetBounds( 221, ButtonTop, ButtonWidth, ButtonHeight );
      end;
      ShowModal;
      if ModalResult = mrBrowse then
      begin
        if BrowseForDir( Application.Handle, ADirPath ) then
          SelPath := InputDlg( ADirPath );
      end;
			if ModalResult = mrOK then
      begin
				AValue := Edit.Text;
        if AValue <> '' then
          Result := AValue;
        TDlgForm.Close;
        exit;
      end;
      if ModalResult = mrCancel then
			begin
        Result := '';
      end;
    finally
      TDlgForm.Free;
    end;
  end; // InputDlg

begin
  AImage := nil;
	case SubItems of
    0 :
      begin
        ADirPath := '';
				InputDlg( ADirPath );
        if SelPath <> '' then
          SendToPath( SelPath );
      end;
    1 :
      begin
        FPath := Selected.SubItems[ 4 ];
        FExt := UpperCase( ExtractFileExt( FPath ) );
        if ( FExt = '.BMP' ) or ( FExt = '.WMF' ) then
				begin
          try
            AImage := TImage.Create( Self );
            AImage.Parent := Self;
						AImage.Picture.LoadFromFile( FPath );
            ClipBoard.Assign( AImage.Picture );
          finally
            AImage.Free;
          end;
        end
        else
        begin
          OldCur := Screen.Cursor;
          Screen.Cursor := crHourGlass;
					CopyBrd := TRichEdit.Create( Self );
          with CopyBrd do
          begin
            Parent := Self;
            PlainText := False;
            Visible := False;
          end;
					if Selected <> nil then
          try
						CopyBrd.Lines.LoadFromFile( FPath );
            CopyBrd.SelectAll;
            CopyBrd.CopyToClipboard;
          finally
            CopyBrd.Free;
            Screen.Cursor := OldCur;
          end;
        end;
      end;
    2 :
      begin
        FNMemo := TMemo.Create( Self );
        FNMemo.Parent := Self;
        FNMemo.Lines.Clear;
				try
					for i := 0 to Items.Count - 1 do
          begin
            if Items[ i ].Selected then
              FNMemo.Lines.Add( Selected.SubItems[ 4 ] + #0 );
          end;
          FNMemo.SelectAll;
          FNMemo.CopyToClipboard;
        finally
					FNMemo.Free;
        end;
      end;
  end;
end; // SendTo


procedure TLsFileListView26.SendTo2( Path : string );
var
	FName : string;
  PName : string;
  DPath : string;
  Drv : string;

	// Resolving Shortcuts
  function GetShellLinkPath( Handle : THandle; LinkFileName : string ) :
      string;
  var
		IUnk : IUnknown;
    pShlLnk : IShellLink;
    pszPath : array[ 0..MAX_PATH - 1 ] of Char;
    win32FD : TWin32FindData;
    ppF : IPersistFile;
		hRes : hResult;
    {$IFNDEF D3_OR_HIGHER}
    pSource : array[ 0..MAX_PATH - 1 ] of wideChar;
		{$ELSE}
    pSource : WideString;
    {$ENDIF}
  begin
    Result := '';
    {$IFNDEF D3_OR_HIGHER}
    CoInitialize( nil );
    if CoCreateInstance( CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
      IID_IShellLink, pShlLnk ) = S_OK then
      if pShlLnk.QueryInterface( IID_IPersistFile, ppF ) = S_OK then
      try
				MultiByteToWideChar( CP_ACP, 0, @LinkFileName[ 1 ], -1, pSource,
					MAX_PATH );
        //  ShowMessage(pSource);    // for debug
        if ppF.Load( pSource, STGM_READ ) = S_OK then
        begin
          hRes := pShlLnk.GetPath( pszPath, MAX_PATH, win32FD, SLGP_SHORTPATH
						 );
          if hRes = S_OK then
            Result := StrPas( pszPath )
					else
            exit;
        end;
      finally
        ppF.Release;
        CoUnInitialize;
      end;
    {$ELSE}
    IUnk := CreateComObject( CLSID_ShellLink );
    pShlLnk := IUnk as IShellLink;
    ppF := IUnk as IPersistFile;
    pSource := LinkFileName;

    hRes := ppF.Load( pWideChar( pSource ), STGM_READ );
		if Succeeded( hRes ) then
    begin
      hRes := pShlLnk.Resolve( Application.Handle, SLR_ANY_MATCH );
      if Succeeded( hRes ) then
      begin
        hRes := pShlLnk.GetPath( @pszPath, MAX_PATH, Win32FD, 0 );
        if Succeeded( hRes ) then
          Result := string( pChar( @pszPath ) );
      end;
		end;
    {$ENDIF}
  end; //GetShellLinkPath

begin
  if Selected = nil then exit;
  if UpperCase( ExtractFileExt( Path ) ) = '.LNK' then
  begin
		FName := GetShellLinkPath( Handle, Path );
		PName := ExtractFileName( Selected.SubItems[ 4 ] );
    DPath := ExtractFilePath( Selected.SubItems[ 4 ] );
    // ShowMessage(FName); // for debug
    if FName = '' then exit;
    Drv := Copy( FName, 1, 3 );
		if ( GetDriveType( PChar( Drv ) ) = DRIVE_REMOVABLE ) then
      SendToDrive( FName )
    else
    begin
      if DirectoryExists( FName ) then
        SendToPath( FName )
      else
        ExecuteFile( 'Open', FName, PName, DPath, SW_SHOW );
    end;
	end
  else if DirectoryExists( Path ) then
		SendToPath( Path );
end; // SendTo2

procedure TLsFileListView26.SendToPath( DestPath : string );
var
  i : integer;
  FSrc : string;
  FDes : string;
  DFName : string;
  Abort : Boolean;
  OldCur : TCursor;
begin
	if not SetCurrentDir( FDirectory ) then exit;
  Abort := False;
  OldCur := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  FSelectedFiles.Clear;
	try
    for i := 0 to Items.Count - 1 do
      if Items[ i ].Selected then
        FSelectedFiles.Add( Items[ i ].SubItems[ 4 ] + #0 );
		for i := 0 to FSelectedFiles.Count - 1 do
    begin
      FSrc := '';
			FDes := '';
      FSrc := FSelectedFiles.Strings[ i ];
      DFName := ExtractFileName( FSrc );
      FDes := DestPath + DFName + #0;
      DoSHFileOp( Parent.Handle, FileOpMode[ 0 ], FSrc, FDes, Abort );
    end;
  finally
    FSelectedFiles.Clear;
    Screen.Cursor := OldCur;
  end;
end; // SendToPath

procedure TLsFileListView26.SendToDrive( DriveID : string );
var
  Drv : Char;
  OldCur : TCursor;
begin
  OldCur := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  Drv := DriveID[ 1 ];
	if not DiskInDrive( Drv, 1 ) then
  begin
    Screen.Cursor := oldCur;
    exit
  end
  else
    SendToPath( DriveID );
  Screen.Cursor := oldCur;
end; // SendToDrive


{***********************************************************************}
{                       LsFileListViewPopUp26                           }
{***********************************************************************}

constructor TLsFileListViewPopUp26.Create( AOwner : TComponent );
var
  sfi : TSHFileInfo;
begin
  inherited Create( AOwner );
  SendToList := TStringList.Create;
  {$IFDEF D4_OR_HIGHER}
  ImagLst := TImageList.Create( Self ); //60
	try
    SetLength( FWinDir, MAX_PATH );
    SetLength( FWinDir, GetWindowsDirectory( PChar( FWinDir ), MAX_PATH ) );
    FWinDir := AddSlash( FWinDir );
    ImagLst.Handle := SHGetFileInfo( PChar( FWinDir ), 0, sfi, sizeOf( sfi ),
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON );
    ImagLst.ShareImages := True;
    ImagLst.BlendColor := clHighLight;
    ImagLst.DrawingStyle := dsTransparent; //dsSelected;
  finally
    Images := ImagLst;
  end;
  {$ENDIF}
end; // Create

destructor TLsFileListViewPopUp26.Destroy;
begin
  SendToList.Free;
  inherited Destroy;
end; // Destroy

function TLsFileListViewPopUp26.AddNewItem( const aCaption : string;
  aShortCut : TShortCut; aChecked, aEnabled : Boolean;
	aGroup : integer; aOnClick : TNotifyEvent;
  hCtx : word; const aName : string ) : TMenuItem;
begin
  Result := NewItem( aCaption, aShortCut, aChecked, aEnabled,
    aOnClick, hCtx, aName );
end; // AddNewItem


procedure TLsFileListViewPopUp26.SetFileListView( Value : TLsFileListView26 );
begin
  FFileListView := Value;
end; // SetFileListView


procedure TLsFileListViewPopUp26.GetSendToSubMenu;
var
  SendToDir,
    FName,
    FullName : string;
  win32FD : TWin32FindData;
  hFindFile : THandle;
  sfi : TSHFileInfo;
  i : integer;
	NewItem : TMenuItem;

  function GetShellPath( Handle : THandle; var DestPath : string;
    nFldr : integer ) : Boolean;
  var
    ShellMalloc : IMALLOC;
    shBuff : pChar;
    idRoot : PItemIDList;
  begin
    Result := False;
    SetLength( DestPath, MAX_PATH );
    if CoGetMalloc( 1, ShellMalloc ) = NOERROR then
    try
      shBuff := PChar( ShellMalloc.Alloc( MAX_PATH ) );
			if assigned( shBuff ) then
      begin
        SHGetSpecialFolderLocation( Handle, nFldr, idRoot );
        // Convert idRoot to a file system path and pass to shBuff.
        if SHGetPathFromIDList( idRoot, shBuff ) then
        begin
          DestPath := shBuff;
          Result := True;
        end;
			end;
    finally
      ShellMalloc.Free( idRoot );
      {$IFDEF D3_OR_HIGHER}
      ShellMalloc._Release; //53
      {$ELSE}
      ShellMalloc.Release;
      {$ENDIF}
      //      ShellMalloc.Free(shBuff);   //53
    end;
  end; // GetShellPath

begin
  SendToList.Clear;
	i := 0;
  if GetShellPath( Handle, SendToDir, CSIDL_SENDTO ) then
  begin
    hFindFile := FindFirstFile( PChar( SlashSep( SendToDir, '*.LNK' ) ), win32FD
       );
    if hFindFile <> INVALID_HANDLE_VALUE then
    try
      repeat
        with win32FD do
				begin
          FName := StrPas( cFileName );
          if ( FName = '.' ) or ( FName = '..' ) then continue;
          FullName := SlashSep( SendToDir, FName );
          SHGetFileInfo( PChar( FullName ), 0, sfi, SizeOf( sfi ),
            SHGFI_SYSICONINDEX or SHGFI_DISPLAYNAME ); //60

          NewItem := AddNewItem( StrPas( sfi.szDisplayName ), 0, False,
            True, 1, ItemOnClick, 0, 'Send_To' + IntToStr( i + 4 ) );
          {$IFDEF D4_OR_HIGHER}
          NewItem.ImageIndex := sfi.iIcon; //60
          {$ENDIF}
          Items.Items[ 3 ].Add( NewItem );
          SendToList.Add( FullName );
					inc( i );
        end;
      until not FindNextFile( hFindFile, win32FD );
    finally
      Windows.FindClose( hFindFile );
    end;
  end;
end; // GetSendToSubMenu


procedure TLsFileListViewPopUp26.BuildItems;
begin
  Items.Add( AddNewItem( '&Open', 0, False, True, 0,
    ItemOnClick, 0, 'ItemOpen' ) ); //Items[0]
  Items.Add( AddNewItem( '&View', 0, False, True, 0,
    ItemOnClick, 0, 'ItemView' ) ); //Items[1]
  Items.Add( NewLine );
  Items.Add( AddNewItem( 'Se&nd To', 0, False, True, 0,
    ItemOnClick, 0, 'SubMenuSend' ) ); //Items[3]
  Items.Add( NewLine );
  Items.Add( AddNewItem( 'Cu&t', 0, False, True, 0,
    ItemOnClick, 0, 'ItemOpCut' ) ); //Items[5]
  Items.Add( AddNewItem( '&Copy', 0, False, True, 0,
		ItemOnClick, 0, 'ItemOpCopy' ) ); //Items[6]
  Items.Add( AddNewItem( '&Paste', 0, False, True, 0,
    ItemOnClick, 0, 'ItemOpPaste' ) ); //Items[7]
  Items.Add( NewLine );
  Items.Add( AddNewItem( '&Rename', 0, False, True, 0,
    ItemOnClick, 0, 'ItemRename' ) ); //Items[9]
  Items.Add( AddNewItem( '&Delete', 0, False, True, 0,
    ItemOnClick, 0, 'ItemDelete' ) ); //Items[10]
  Items.Add( NewLine );
	Items.Add( AddNewItem( '&Attributes ...', 0, False, True, 0,
    ITemOnClick, 0, 'ItemFileAttr' ) ); //Items[12]
  Items.Add( NewLine );
  Items.Add( AddNewItem( '&New Folder ...', 0, False, True, 0,
    ItemOnClick, 0, 'ItemFolder' ) ); //Items[14]
  // Items[3] SendTo SubItems
  Items.Items[ 3 ].Add( AddNewItem( 'Any Folder ...', 0, False, True, 0,
    ItemOnClick, 0, 'Send_To' + IntToStr( 0 ) ) );
  Items.Items[ 3 ].Add( AddNewItem( 'Clipboard as Contents', 0, False, True, 0,
    ItemOnClick, 0, 'Send_To' + IntToStr( 1 ) ) );
  Items.Items[ 3 ].Add( AddNewItem( 'Clipboard as FileName', 0, False, True, 0,
    ItemOnClick, 0, 'Send_To' + IntToStr( 2 ) ) );
  Items.Items[ 3 ].Add( NewLine );
  GetSendToSubMenu;
end; // BuildItems

procedure TLsFileListViewPopUp26.ItemOnClick( Sender : TObject );
var
  i : integer;
begin
  if TMenuItem( Sender ).Name = 'ItemOpen' then
    FFileListView.OpenItem
  else if TMenuItem( Sender ).Name = 'ItemView' then
		FFileListView.ViewFile
  else if TMenuItem( Sender ).Name = 'ItemOpCut' then
    FFileListView.CutCopy( 2 )
  else if TMenuItem( Sender ).Name = 'ItemOpCopy' then
    FFileListView.CutCopy( 0 )
  else if TMenuItem( Sender ).Name = 'ItemOpPaste' then
    FFileListView.Paste
  else if TMenuItem( Sender ).Name = 'ItemRename' then
    FFileListView.RenameFile
  else if TMenuItem( Sender ).Name = 'ItemDelete' then
    FFileListView.DeleteItems
  else if TMenuItem( Sender ).Name = 'ItemFileAttr' then
    FFileListView.FileAttr
  else if TMenuItem( Sender ).Name = 'ItemFolder' then
		FFileListView.NewFolder
  else if Pos( 'Send_To', TMenuItem( Sender ).Name ) = 1 then
  begin
    i := StrToIntDef( Copy( TMenuItem( Sender ).Name, 8, 2 ), -1 );
    if ( i > -1 ) and ( i < 3 ) then
      FFileListView.SendTo( i )
    else if ( i > 3 ) then
      FFileListView.SendTo2( SendToList[ i - 4 ] );
  end
end; // ItemOnClick

procedure TLsFileListViewPopUp26.PopUp( X, Y : integer );
var
  i : integer;
  Ext : string;
begin
  Ext := '';
  if ( FFileListView.Selected <> nil ) then
    Ext := ( Uppercase( ExtractFileExt( FFileListView.Selected.SubItems[ 4 ] ) )
       );
  Items[ 0 ].Enabled := FFileListView.Selected <> nil;
  Items[ 1 ].Enabled := False;
  if ( FFileListView.Selected <> nil ) then
	begin
    for i := Low( FileExt ) to High( FileExt ) do
      if ( Ext = FileExt[ i ] ) then
        Items[ 1 ].Enabled := True;
  end;
  Items[ 3 ].Enabled := FFileListView.Selected <> nil;
  Items[ 5 ].Enabled := FFileListView.Selected <> nil;
  Items[ 6 ].Enabled := FFileListView.Selected <> nil;
  Items[ 7 ].Enabled := FFileListView.FSelectedFiles.Count <> 0;
	Items[ 9 ].Enabled := ( FFileListView.Selected <> nil ) and
    ( FFileListView.SelCount = 1 );
  Items[ 10 ].Enabled := FFileListView.Selected <> nil;
  Items[ 12 ].Enabled := FFileListView.Selected <> nil;
  Items[ 14 ].Enabled := UpperCase( FFileListView.Directory ) <> 'DRIVES';

  Items[ 3 ][ 1 ].Enabled := FFileListView.Selected <> nil;
  Items[ 3 ][ 2 ].Enabled := FFileListView.Selected <> nil;
  Items[ 3 ][ 3 ].Enabled := False;
  if ( FFileListView.Selected <> nil ) and ( FFileListView.SelCount = 1 ) then
  begin
    for i := Low( FileExt ) to High( FileExt ) do
      if ( Ext = FileExt[ i ] ) then
        Items[ 3 ][ 3 ].Enabled := True;
		if ( Ext = '.BMP' ) or ( Ext = '.WMF' ) then
      Items[ 3 ][ 3 ].Enabled := True;
  end;
  Items[ 3 ][ 4 ].Enabled := FFileListView.Selected <> nil;
  inherited Popup( X + 10, Y + 10 );
end; // PopUp

/////End of TLsFileListView26/////


{ ****** Register ****** }

procedure Register;
begin
  RegisterComponents( 'File Utils', [ TLsDirTree10 ] );
  RegisterComponents( 'File Utils', [ TLsDirTreeCombo26 ] );
  RegisterComponents( 'File Utils', [ TLsFileListView26 ] );
  {$IFNDEF D5_OR_HIGHER} //53
  RegisterPropertyEditor( TypeInfo( TAboutProperty ), TLsDirTree10,
    'ABOUT', TAboutProperty );
  RegisterPropertyEditor( TypeInfo( TAboutProperty ), TLsDirTreeCombo26,
    'ABOUT', TAboutProperty );
  RegisterPropertyEditor( TypeInfo( TAboutProperty ), TLsFileListView26,
		'ABOUT', TAboutProperty );
  {$ENDIF}
end;

end.

