Solved

Sorting files

Posted on 1998-10-27
18
1,189 Views
Last Modified: 2008-02-20
I wanna sort the files in filelistbox. Ex. Sort by date,
Sort by name. And display them in same filelistbox.

mhieta
0
Comment
Question by:mhieta
  • 8
  • 6
  • 4
18 Comments
 
LVL 3

Accepted Solution

by:
bryan7 earned 10 total points
ID: 1344561
To sort by name:

Var k,b: Integer;
      s: string;
begin
FOR k = 1 TO Ndir DO
begin
a:= k;
FOR B = k TO Ndir DO
IF z(B) < z(a) THEN a:= B;

s:= z(a);
z(a):= z(k);
z(k):= s;
end;
end;

z must be the a strings array, then it's sort alphabetically.
( it worked in Basic, dunno if so in Delphi, but it's a fast sorting procedure )

bryan

0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344562
sooooooorry,

In the FOR ... to  ... statements
it must b   FOR K:= 1 to ..
     and
FOR B:= K to ....

I forgot the  :  

bryan

0
 
LVL 4

Expert Comment

by:erajoj
ID: 1344563
Sorry, guys!
The TFileListBox is already sorted, and you can only do temporary sorts on it.

To reverse the sortorder (temporarily):
  for iIndex := FileListBox1.Items.Count-1 downto 1 do FileListBox1.Items.Move( 0, iIndex );

To fix this, inherit the TFileListBox and make your own component with custom sorts. Would you like some help on that?
Or, make your own file listbox from an ordinary TListBox. It's quite easy, maybe 20-30 lines of code, including sorts.

And Bryan7, do you really think your answer is sufficient enough to fully answer mhieta's question. Please try to use comments until you know the answer is the right one, ok?

/// John

0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344564
well.. noone answered..

I know my answer is a crap.
But noone dropped anything...
I guess the points are yours if noone drops any other comment.

bryan =)

0
 
LVL 4

Expert Comment

by:erajoj
ID: 1344565
Well, you're right. There actually is no good answer to this question.
To be able to do the things mhieta want's you have to take an other approach, unfortunately...
Sorry it I sounded harsh, not my intention. Of course you should answer questions in order to gather points. Just try to make sure the answers are the wanted ones.

:-)

/// John

0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344566
Well, I just dropped a way to alphabetically sort a strings array.
I know that's not all what's needed, ( maybe ), but that's all I know.
I haven't still used a FileListBox, but I thought Mhieta knew how to use it,
so I just gave a way to sort it, and thought Mhieta would know how to implement it.

Sorry if I'm not helping too much.

bryan
0
 
LVL 2

Author Comment

by:mhieta
ID: 1344567
Thanks all for helping me. If someone answer how to sort by date. ex. filemanager.
0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344568
uh?
You were supposed to reject my answer.. and wait for some other comments..

  ??? ( so, did my answer help you after all ? )

bryan
0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344569
Hmm.. from looking at your profile I see you are new here,,
If you want I can use my points to re-ask your question.

bryan

0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 4

Expert Comment

by:erajoj
ID: 1344570
Hi all,
Stayed up last night to make a TFileListBoxEx with sorting incorporated.
I'm not finished yet, but if you still want it, I'll finish it and give you the source
as a comment. But if you do not want it, there is no need for me to continue on it, ok?

/// John
0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344571
erajoj>>> If you do so, I'll give you the points that Mhieta gave me.
I think he/she still doesn't know very well how E-E works

bryan

0
 
LVL 4

Expert Comment

by:erajoj
ID: 1344572
Bah, humbug! ;-)

Keep the points if we come to that! The points are of no importance at all.
That's not the issue here, the satisfaction of the questioner is.

/// John
0
 
LVL 3

Expert Comment

by:bryan7
ID: 1344573
yep, I know.
I'm learning a lot at E-E.

bryan

0
 
LVL 2

Author Comment

by:mhieta
ID: 1344574
You are right bryan7 i'm new here, erajoj i want that source code because that could help
me. erajoj is right, keep the points. if erajoj's source code not help me, bryan7 re-ask the question.
ps. maybe i'm too kind about the points, i think.

mhieta
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1344575
Hi,
Do you want to be able to see the size/date in the list?
Or is the sorting enough?

/// John
0
 
LVL 2

Author Comment

by:mhieta
ID: 1344576
Hi,
That would be nice.

mhieta
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1344577
Hi again,
Sorry it took so long! I had a lot of other things to do.
Here is a simple implementation of a fully sortable FileListBox.
Install it as "New Component" and use it just like the regular FileListBox.
There are a few new properties:
  - Ascending, direction of sort
  - Columns, selects visible extra columns
  - SortBy, sorting by name, type, date or size
  - ColumnWidth, sets xtra column's widths (in percent)

Here goes:

unit FileListBoxEx;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, FileCtrl;

type
  TFileSortTypes      = ( stName, stType, stModified, stSize ); { supported sorts }
  TFileColumns        = ( fcModified, fcSize ); { configurable columns }
  TFileColumnsSet     = set of TFileColumns;

  PFileData = ^TFileData;
  TFileData = record { file data record }
    Name : string;
    Glyph: TBitmap;
    Attr : Integer;
    Date : TDateTime;
    Size : Integer;
  end;

  TFileListBoxEx = class(TFileListBox)
  private
    FFileSortBy : TFileSortTypes;
    FAscending  : Boolean;
    FColumns    : TFileColumnsSet;
    FColWidths  : array[ TFileColumns ] of Integer;
    FileList    : TList; { main file data list }
    procedure SetSortBy( SortType: TFileSortTypes );
    procedure SetAscending( bAscending: Boolean );
    procedure SetColumns( cols: TFileColumnsSet );
    function  GetColWidths( col: TFileColumns ): Integer;
    procedure SetColWidths( col: TFileColumns; Width: Integer );
    { Private declarations }
  protected
    procedure FileSort;
    procedure CopyFileData;
    procedure ReadFileNames; override;
    procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
    procedure Sort( Compare: TListSortCompare );
  public
    constructor Create(AOwner: TComponent); override;
    property    ColumnWidth[ col: TFileColumns ]: Integer read GetColWidths write SetColWidths;
  published
    property SortBy    : TFileSortTypes read FFileSortBy write SetSortBy;
    property Ascending : Boolean read FAscending write SetAscending;
    property Columns   : TFileColumnsSet read FColumns write SetColumns;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Custom', [TFileListBoxEx]);
end;

constructor TFileListBoxEx.Create(AOwner: TComponent); { creates standard list }
begin
  inherited Create(AOwner);
  FColWidths[ fcModified ] := 20; { 20 percent width }
  FColWidths[ fcSize ]     := 20; { 20 percent width }
  FileList                 := TList.Create; { main list }
  Sorted                   := False;        { must be false! }
  FFileSortBy              := stName;       { standard alpha sort }
  FAscending               := True;         { a-z }
end;

procedure TFileListBoxEx.SetSortBy( SortType: TFileSortTypes );
begin
  FFileSortBy := SortType;
  Items.Clear;
  FileSort;
  CopyFileData;
  Repaint;
end;

procedure TFileListBoxEx.SetAscending( bAscending: Boolean );
begin
  FAscending := bAscending;
  Items.Clear;
  FileSort;
  CopyFileData;
  Repaint;
end;

procedure TFileListBoxEx.SetColumns( cols: TFileColumnsSet );
begin
  FColumns := cols;
  RePaint;
end;

function  TFileListBoxEx.GetColWidths( col: TFileColumns ): Integer;
begin
  Result := FColWidths[ col ];
end;

procedure TFileListBoxEx.SetColWidths( col: TFileColumns; Width: Integer );
begin
  FColWidths[ col ] := Width;
  Repaint;
end;

{ MATH ROUTINES ============================================================== }

function Sign( Value: Extended ): Integer;
begin
  if ( Value < 0 ) then
    Result := -1
  else if ( Value > 0 ) then
    Result := 1
  else
    Result := 0;
end;

{ SORTING ROUTINES =========================================================== }

function  AlphaSort( Item1, Item2 : Pointer ): Integer;
var
  pData1, pData2: PFileData;
begin
  pData1 := Item1; pData2 := Item2;
  Result := AnsiCompareText( pData1^.Name, pData2^.Name );
end;

function  ExtensionSort( Item1, Item2 : Pointer ): Integer;
var
  pData1, pData2: PFileData;
begin
  pData1 := Item1; pData2 := Item2;
  Result := CompareText( ExtractFileExt( pData1^.Name ), ExtractFileExt( pData2^.Name ) );
  if ( Result = 0 ) then Result := AlphaSort( Item1, Item2 );
end;

function  SizeSort( Item1, Item2 : Pointer ): Integer;
var
  pData1, pData2: PFileData;
begin
  pData1 := Item1; pData2 := Item2;
  Result := pData1^.Size - pData2^.Size;
  if ( Result = 0 ) then Result := AlphaSort( Item1, Item2 );
end;

function  DateTimeSort( Item1, Item2 : Pointer ): Integer;
var
  pData1, pData2: PFileData;
begin
  pData1 := Item1; pData2 := Item2;
  Result := Sign( pData1^.Date - pData2^.Date );
  if ( Result = 0 ) then Result := AlphaSort( Item1, Item2 );
end;

procedure TFileListBoxEx.Sort( Compare: TListSortCompare );
begin
  if ( FileList.Count > 0 ) then
  begin
    FileList.Sort( Compare );
  end;
end;

procedure TFileListBoxEx.FileSort;
begin
  case FFileSortBy of
    stName:     Sort( AlphaSort );
    stType:     Sort( ExtensionSort );
    stModified: Sort( DateTimeSort );
    stSize:     Sort( SizeSort );
  end;
end;

{ DATA TRANSFER ROUTINES ===================================================== }

procedure TFileListBoxEx.CopyFileData;
var
  iIndex : Integer;
  pData  : PFileData;
begin
  Items.BeginUpdate;
  if ( FAscending ) then
    for iIndex := 0 to FileList.Count - 1 do
    begin
      pData := PFileData( FileList[ iIndex ] );
      Items.AddObject( pData^.Name, TObject( pData ) );
    end
  else
    for iIndex := FileList.Count - 1 downto 0 do
    begin
      pData := PFileData( FileList[ iIndex ] );
      Items.AddObject( pData^.Name, TObject( pData ) );
    end;
  Items.EndUpdate;
end;

{ FILE ROUTINES ============================================================== }

procedure TFileListBoxEx.ReadFileNames;
var
  AttrIndex : TFileAttr;
  I         : Integer;
  FileExt   : string;
  MaskPtr   : PChar;
  Ptr       : PChar;
  AttrWord  : Word;
  FileInfo  : TSearchRec;
  SaveCursor: TCursor;
  pObj      : PFileData; { changed here }

const
   Attributes: array[TFileAttr] of Word = (faReadOnly, faHidden, faSysFile,
     faVolumeID, faDirectory, faArchive, 0);

begin
      { if no handle allocated yet, this call will force
        one to be allocated incorrectly (i.e. at the wrong time.
        In due time, one will be allocated appropriately.  }
  AttrWord := DDL_READWRITE;
  if HandleAllocated then
  begin
    { Set attribute flags based on values in FileType }
    for AttrIndex := ftReadOnly to ftArchive do
      if AttrIndex in FileType then
        AttrWord := AttrWord or Attributes[AttrIndex];

    ChDir(FDirectory); { go to the directory we want }
    for I := 0 to FileList.Count - 1 do Dispose( PFileData( FileList[ I ] ) ); { changed here }
    FileList.Clear; { clear the filelist }
    Clear; { clear the listbox }

    I := 0;
    SaveCursor := Screen.Cursor;
    try
      MaskPtr := PChar(FMask);
      while MaskPtr <> nil do
      begin
        Ptr := StrScan (MaskPtr, ';');
        if Ptr <> nil then
          Ptr^ := #0;
        if FindFirst(MaskPtr, AttrWord, FileInfo) = 0 then
        begin
          repeat            { exclude normal files if ftNormal not set }
            if (ftNormal in FileType) or (FileInfo.Attr and AttrWord <> 0) then
            begin { changed here }
              New( pObj ); { changed here }
              with pObj^ do begin { changed here }
                Glyph := nil; { changed here }
                Attr  := FileInfo.Attr; { changed here }
                Date  := FileDateToDateTime( FileInfo.Time ); { changed here }
                Size  := FileInfo.Size; { changed here }
              end; { changed here }
              if FileInfo.Attr and faDirectory <> 0 then
              begin
                pObj^.Name := Format('[%s]',[FileInfo.Name]); { changed here }
                if ShowGlyphs then
                  pObj^.Glyph := DirBMP; { changed here }
              end
              else
              begin
                FileExt := AnsiLowerCase(ExtractFileExt(FileInfo.Name));
                pObj^.Glyph := UnknownBMP; { changed here }
                if (FileExt = '.exe') or (FileExt = '.com') or
                  (FileExt = '.bat') or (FileExt = '.pif') then
                  pObj^.Glyph := ExeBMP; { changed here }
                pObj^.Name := FileInfo.Name; { changed here }
              end;
              I := FileList.Add( pObj ); { changed here }
            end; { changed here }
            if I = 100 then
              Screen.Cursor := crHourGlass;
          until FindNext(FileInfo) <> 0;
          FindClose(FileInfo);
        end;
        if Ptr <> nil then
        begin
          Ptr^ := ';';
          Inc (Ptr);
        end;
        MaskPtr := Ptr;
      end;
      FileSort; { changed here }
      CopyFileData;
    finally
      Screen.Cursor := SaveCursor;
    end;
    Change;
  end;
end;

{ GRAPHIC ROUTINES =========================================================== }

procedure TFileListBoxEx.DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  Bitmap      : TBitmap;
  sSize, sDate: string;
  pData       : PFileData;
  R1, R2      : TRect;
begin
  pData := Pointer( Items.Objects[ Index ] );
  with Canvas do
  begin
    sSize := IntToStr( pData^.Size );
    sDate := DateToStr( pData^.Date );
    FillRect( Rect );
    Rect.Left  := Rect.Left + 2;
    Rect.Right := Rect.Right - 4;
    R1 := Rect;
    R2 := Rect;
    if ( [ fcSize, fcModified ] = FColumns ) then
    begin
      R2.Left  := R2.Right - ( Rect.Right - Rect.Left ) * FColWidths[ fcSize ] div 100;
      R1.Right := R2.Left;
      R1.Left  := R2.Right - ( Rect.Right - Rect.Left ) * ( FColWidths[ fcModified ] + FColWidths[ fcSize ] ) div 100;
      Rect.Right := R1.Left;
    end else if ( fcSize in FColumns ) or ( fcModified in FColumns ) then
    begin
      if ( fcSize in FColumns ) then
        R2.Left := R2.Right - ( Rect.Right - Rect.Left ) * FColWidths[ fcSize ] div 100
      else
        R2.Left := R2.Right - ( Rect.Right - Rect.Left ) * FColWidths[ fcModified ] div 100;
      Rect.Right := R2.Left;
    end;

    if ShowGlyphs then
    begin
      Bitmap := pData^.Glyph;
      if Assigned(Bitmap) then
      begin
        BrushCopy(Bounds(Rect.Left + 2,
                  (Rect.Top + Rect.Bottom - Bitmap.Height) div 2,
                  Bitmap.Width, Bitmap.Height),
                  Bitmap, Bounds(0, 0, Bitmap.Width, Bitmap.Height),
                  Bitmap.Canvas.Pixels[0, Bitmap.Height - 1]);
        Rect.Left := Rect.Left + Bitmap.width + 6;
      end;
    end;
    Windows.DrawTextEx( Handle, PChar( Items[ Index ] ), -1, Rect, DT_END_ELLIPSIS or DT_LEFT or DT_VCENTER, nil );
    if ( [ fcSize, fcModified ] = FColumns ) then
    begin
      Windows.DrawTextEx( Handle, PChar( sDate ), -1, R1, DT_END_ELLIPSIS or DT_LEFT or DT_VCENTER, nil );
      Windows.DrawTextEx( Handle, PChar( sSize ), -1, R2, DT_END_ELLIPSIS or DT_RIGHT or DT_VCENTER, nil );
    end else if ( fcSize in FColumns ) then
      Windows.DrawTextEx( Handle, PChar( sSize ), -1, R2, DT_END_ELLIPSIS or DT_RIGHT or DT_VCENTER, nil )
    else if ( fcModified in FColumns ) then
      Windows.DrawTextEx( Handle, PChar( sDate ), -1, R2, DT_END_ELLIPSIS or DT_LEFT or DT_VCENTER, nil );
  end;
end;

end.

If there are bugs or if you have questions, please contact me by email (see my profile).
Enjoy!

/// John
0
 
LVL 2

Author Comment

by:mhieta
ID: 1344578
Thanks all for participating for solving this question of mine, especially erajoj for that
full source code.

mhieta
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now