kretzschmar
asked on
qow 17: (QUICKY) how to fill a treeview with a directorytree?
hi experts,
i am starting a new quest: qow = question of the week :-)
each week i will introduce a new simple? question.
now qow 17 (a quicky)
the first working solution will get the points (a graded).
sorry, top 15 experts, you are not allowed to solve this
q, only other can solve this question :-(
well the question is:
an sample is needed
how to fill a treeview with a directorytree
(like explorer)?
let see
meikl ;-)
(the points may reduced to 25 pts by a modarator,
before i do accept)
i am starting a new quest: qow = question of the week :-)
each week i will introduce a new simple? question.
now qow 17 (a quicky)
the first working solution will get the points (a graded).
sorry, top 15 experts, you are not allowed to solve this
q, only other can solve this question :-(
well the question is:
an sample is needed
how to fill a treeview with a directorytree
(like explorer)?
let see
meikl ;-)
(the points may reduced to 25 pts by a modarator,
before i do accept)
HI, meikl,
Would you mind to formulate your qow more explicitly:
1. we already have the directory tree (some sort of outline)
and want simply copy it to treeview.
2. we have a name of some directory and want to fill the treeview with all the subdirectories of this directory?
Sincerely,
Nestorua.
Would you mind to formulate your qow more explicitly:
1. we already have the directory tree (some sort of outline)
and want simply copy it to treeview.
2. we have a name of some directory and want to fill the treeview with all the subdirectories of this directory?
Sincerely,
Nestorua.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
cesario,
as NEW top15 member,
you will get no point from this q
well, why i spent so low points?
qows comes periodically each week one,
sometimes (i tend to do this more often)
i provide for each different
solution the same points,
therefore i must care
about my points-account
(sometimes i may have ask a q for myself)
well, why qows?
it was just an idea
- for providing points for none top15 members
- for learning from each other
- for a better community here
- for just for fun
... and more benefits
well,
and don't worry,
i run not out of ?simple questíons :-)))
meikl ;-)
as NEW top15 member,
you will get no point from this q
well, why i spent so low points?
qows comes periodically each week one,
sometimes (i tend to do this more often)
i provide for each different
solution the same points,
therefore i must care
about my points-account
(sometimes i may have ask a q for myself)
well, why qows?
it was just an idea
- for providing points for none top15 members
- for learning from each other
- for a better community here
- for just for fun
... and more benefits
well,
and don't worry,
i run not out of ?simple questíons :-)))
meikl ;-)
ASKER
to nestorua,
use the ttreeview and try to populate it with the directory structure of drive c:\ (for example)
to raidos,
looks good
meikl ;-)
(i'm not quick enough) :-))
use the ttreeview and try to populate it with the directory structure of drive c:\ (for example)
to raidos,
looks good
meikl ;-)
(i'm not quick enough) :-))
ASKER
to nestorua,
i will try on the next qow
to be clearer with the question
(i was a bit in hurry by this one)
meikl ;-)
i will try on the next qow
to be clearer with the question
(i was a bit in hurry by this one)
meikl ;-)
procedure Populate(aTreeView: TTreeView; aRoot: TTreeNode;Path: string; Recurse: boolean);
var
NewNode: TTreeNode;
SRec: TSearchRec;
begin
if FindFirst(Path + '*.*', SysUtils.faAnyFile, SRec) = 0 then
repeat
if (sRec.Name = '.') or (sRec.Name = '..') then
Continue;
NewNode := aTreeView.Items.AddChild(a Root, SRec.Name);
if Recurse and ((srec.Attr and sysutils.faDirectory) <> 0) then
Populate(aTreeView, NewNode, Path + srec.name + '\', True);
until
FindNext(SRec) <> 0;
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
Populate(TreeView1, nil, 'c:\', True);
end;
var
NewNode: TTreeNode;
SRec: TSearchRec;
begin
if FindFirst(Path + '*.*', SysUtils.faAnyFile, SRec) = 0 then
repeat
if (sRec.Name = '.') or (sRec.Name = '..') then
Continue;
NewNode := aTreeView.Items.AddChild(a
if Recurse and ((srec.Attr and sysutils.faDirectory) <> 0) then
Populate(aTreeView, NewNode, Path + srec.name + '\', True);
until
FindNext(SRec) <> 0;
end;
procedure TForm1.Button1Click(Sender
begin
Populate(TreeView1, nil, 'c:\', True);
end;
Hi meikl,
hi all.
I'm glad that qow problem was succesfully solved. Can I provide my sample for no-points?
----
Igor
hi all.
I'm glad that qow problem was succesfully solved. Can I provide my sample for no-points?
----
Igor
ASKER
sure, igor, you can provide your sample
i'm also happy that i can go on
meikl ;-)
i'm also happy that i can go on
meikl ;-)
Ok, then there is my version. It allow to scan drives and place result into TTreeView.
// An advantage of this technique is that user able to work with directories
// tree and see which of branches can be expanded while scanning is in progress
// Once user click on node, and directory still not scanned, priority of
// according thread increased to allow user see result of scanning ASAP.
// Scanned and "in progress" directories shown in different colors.
sample application can be found at:
http://i-g-o-r.virtualave.net/zip/drivescan.zip
-----
Igor.
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
//
// Basic classes to background scan drive's directory using threads
//
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
unit DSClasses;
interface
uses
Classes, SysUtils, ComCtrls;
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
type
TScanThread = class(TThread)
private
FNode: TTreeNode; // parent node of TreeView to include directories
FTreeView: TTreeView; // TreeView that keeps direcoris tree
FPath: String; // current path to scan
FStrings: TStrings; // TStringList to show info about running threads
// and keep references to allow termination
FFoundDir: String; // used as parameter for ScanSubdirectory method
FExtCounter: ^Integer; // pointer to processed directories count
protected
procedure Execute; override;
procedure ScanSubdirectory;
procedure RemoveInfoFromListBox;
public
// APath - path to scan without backslash
// ATreeView - control to place result
// ANode - parent directory node
// AStrings - keep all currently running threads
// ACount - point to counter (Integer type) of processed directories
constructor Create(const APath: String; ATreeView: TTreeView;
ANode: TTreeNode; AStrings: TStrings; ACount: Pointer);
destructor Destroy; override;
end;
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
implementation
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
//
// TScanThread
//
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
constructor TScanThread.Create(const APath: String; ATreeView: TTreeView;
ANode: TTreeNode; AStrings: TStrings; ACount: Pointer);
begin
Inherited Create(True);
FNode := ANode;
// mark node as "in progress"
if FNode <> nil then
FNode.Data := Self;
FPath := APath;
FTreeView := ATreeView;
FStrings := AStrings;
FExtCounter := ACount;
inc(FExtCounter^);
FreeOnTerminate := True;
// make it lowest to allow increase it in runtime when user needs
// to scan directory ASAP (TreeView's node clicked)
Priority := tpLowest;
FStrings.AddObject(FPath, Self);
Resume;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
destructor TScanThread.Destroy;
begin
if (FNode <> nil) then
begin
if not Terminated then
begin
// mark node as "ready"
FNode.Data := nil;
FTreeView.Invalidate;
end
else
// mark node as "terminated"
FNode.Data := Pointer(-1);
end;
Inherited;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TScanThread.Execute;
var
SR: TSearchRec;
begin
if FindFirst(FPath+'\*.*', faDirectory, SR) = 0 then
try
repeat
if (SR.Attr and faDirectory <>0) and (Copy(SR.Name, 1, 1) <> '.') then
begin
FFoundDir := SR.Name;
Synchronize(ScanSubdirecto ry);
end;
until (FindNext(SR) <> 0) or Terminated;
finally
FindClose(SR)
end;
Synchronize(RemoveInfoFrom Listbox);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TScanThread.ScanSubdirecto ry;
var
ST: TScanThread;
begin
// if thread was terminated, then do not allow to run "child" thread
if not Terminated then
ST := TScanThread.Create(FPath + '\' + FFoundDir, FTreeView,
FTreeView.Items.AddChild(F Node, FFoundDir), FStrings, FExtCounter);
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TScanThread.RemoveInfoFrom ListBox;
begin
try
FStrings.Delete(FStrings.I ndexOfObje ct(Self))
except
end;
end;
end.
// An advantage of this technique is that user able to work with directories
// tree and see which of branches can be expanded while scanning is in progress
// Once user click on node, and directory still not scanned, priority of
// according thread increased to allow user see result of scanning ASAP.
// Scanned and "in progress" directories shown in different colors.
sample application can be found at:
http://i-g-o-r.virtualave.net/zip/drivescan.zip
-----
Igor.
//------------------------
//
// Basic classes to background scan drive's directory using threads
//
//------------------------
unit DSClasses;
interface
uses
Classes, SysUtils, ComCtrls;
//------------------------
type
TScanThread = class(TThread)
private
FNode: TTreeNode; // parent node of TreeView to include directories
FTreeView: TTreeView; // TreeView that keeps direcoris tree
FPath: String; // current path to scan
FStrings: TStrings; // TStringList to show info about running threads
// and keep references to allow termination
FFoundDir: String; // used as parameter for ScanSubdirectory method
FExtCounter: ^Integer; // pointer to processed directories count
protected
procedure Execute; override;
procedure ScanSubdirectory;
procedure RemoveInfoFromListBox;
public
// APath - path to scan without backslash
// ATreeView - control to place result
// ANode - parent directory node
// AStrings - keep all currently running threads
// ACount - point to counter (Integer type) of processed directories
constructor Create(const APath: String; ATreeView: TTreeView;
ANode: TTreeNode; AStrings: TStrings; ACount: Pointer);
destructor Destroy; override;
end;
//------------------------
implementation
//------------------------
//
// TScanThread
//
//------------------------
constructor TScanThread.Create(const APath: String; ATreeView: TTreeView;
ANode: TTreeNode; AStrings: TStrings; ACount: Pointer);
begin
Inherited Create(True);
FNode := ANode;
// mark node as "in progress"
if FNode <> nil then
FNode.Data := Self;
FPath := APath;
FTreeView := ATreeView;
FStrings := AStrings;
FExtCounter := ACount;
inc(FExtCounter^);
FreeOnTerminate := True;
// make it lowest to allow increase it in runtime when user needs
// to scan directory ASAP (TreeView's node clicked)
Priority := tpLowest;
FStrings.AddObject(FPath, Self);
Resume;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
destructor TScanThread.Destroy;
begin
if (FNode <> nil) then
begin
if not Terminated then
begin
// mark node as "ready"
FNode.Data := nil;
FTreeView.Invalidate;
end
else
// mark node as "terminated"
FNode.Data := Pointer(-1);
end;
Inherited;
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TScanThread.Execute;
var
SR: TSearchRec;
begin
if FindFirst(FPath+'\*.*', faDirectory, SR) = 0 then
try
repeat
if (SR.Attr and faDirectory <>0) and (Copy(SR.Name, 1, 1) <> '.') then
begin
FFoundDir := SR.Name;
Synchronize(ScanSubdirecto
end;
until (FindNext(SR) <> 0) or Terminated;
finally
FindClose(SR)
end;
Synchronize(RemoveInfoFrom
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TScanThread.ScanSubdirecto
var
ST: TScanThread;
begin
// if thread was terminated, then do not allow to run "child" thread
if not Terminated then
ST := TScanThread.Create(FPath + '\' + FFoundDir, FTreeView,
FTreeView.Items.AddChild(F
end;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
procedure TScanThread.RemoveInfoFrom
begin
try
FStrings.Delete(FStrings.I
except
end;
end;
end.
hi meikl,
"am starting a new quest: qow = question of the week :-)"
actually its 4 mnts old now mmm are you cuting and pasting the header
i see you got your 25 point problem sorted :)
igor,
your screensaver from last time was quite impressive,just like the real thing.messing with the maths had some interesting effects ,like a laser show from top left corner etc :-)
"am starting a new quest: qow = question of the week :-)"
actually its 4 mnts old now mmm are you cuting and pasting the header
i see you got your 25 point problem sorted :)
igor,
your screensaver from last time was quite impressive,just like the real thing.messing with the maths had some interesting effects ,like a laser show from top left corner etc :-)
ASKER
>are you cuting and pasting the header
yes, i'm too lazy
yes, i'm too lazy
yep Barry, something like laser....
I'v got enexpected results making samples for qow, may be it is one of reason why I like this quest :-)
I'v got enexpected results making samples for qow, may be it is one of reason why I like this quest :-)
HI, meikl,
Here is my solution.
unit frmMain;
{------------------------- ---------- ---------- }
INTERFACE
{------------------------- ---------- ---------- }
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls, ImgList, ToolWin;
type
TFormMain = class(TForm)
tvAllDirs: TTreeView;
CoolBar1: TCoolBar;
tbMain: TToolBar;
ToolButton1: TToolButton;
tbFillTreeView: TToolButton;
ToolButton3: TToolButton;
tbEXIT: TToolButton;
ToolButton5: TToolButton;
ImageList1: TImageList;
procedure tvAllDirsExpanded(Sender: TObject; Node: TTreeNode);
procedure tbEXITClick(Sender: TObject);
procedure tbFillTreeViewClick(Sender : TObject);
private
function GetOneLevelNode(ParentNode : TTreeNode; tv: TTreeView): boolean;
procedure FillTreeViewWithDriveNames (tv: TTreeView);
function GetPathFromNode(Node: TTreeNode): string;
{ Private declarations }
public
{ Public declarations }
end;
var
FormMain: TFormMain;
{------------------------- ---------- ---------- -----}
IMPLEMENTATION
{------------------------- ---------- ---------- -----}
{$R *.dfm}
{------------------------- ---------- ---------- ------}
function TFormMain.GetOneLevelNode( ParentNode : TTreeNode; tv: TTreeView): boolean;
var lpFileName: PChar;
lpFindFileData: TWIN32FindData;
h: THandle;
HasSibling: boolean;
{---}
procedure AddChildNode;
var Node: TTreeNode;
begin
with lpFindFileData do
if ((dwFileAttributes=FILE_AT TRIBUTE_DI RECTORY) and
(String(cFileName)<>'.') and (String(cFileName)<>'..'))
then
with tv.Items.AddChild(ParentNo de, String(cFileName)+'\') do
begin
ImageIndex:=2;
SelectedIndex:=3;
end;
end;
{---}
begin
Result:=False;
//
lpFileName:=PChar(GetPathF romNode(Pa rentNode)+ '*.*');
h:=FindFirstFile(lpFileNam e, lpFindFileData);
//
if h=INVALID_HANDLE_VALUE
then EXIT
else AddChildNode;
//
HasSibling:=FindNextFile(h , lpFindFileData);
while HasSibling do
begin
AddChildNode;
HasSibling:=FindNextFile(h , lpFindFileData);
end;
//
ParentNode.AlphaSort;
//
Result:=ParentNode.HasChil dren;
end;
{------------------------- ---------- ---------- ---------}
procedure TFormMain.FillTreeViewWith DriveNames (tv: TTreeView);
var nLength,
nBufferLength: integer;
lpBuffer,
lpDriveName: PAnsiChar;
Node: TTreeNode;
begin
nBufferLength:=254;
GetMem(lpBuffer, nBufferLength+1);
nLength:=GetLogicalDriveSt rings(nBuf ferLength, lpBuffer);
//
lpDriveName:=lpBuffer;
//
while nLength>0 do
begin
Node:=tv.Items.Add(NIL, lpDriveName);
Node.ImageIndex:=2;
Node.SelectedIndex:=3;
if GetDriveType(lpDriveName)= DRIVE_FIXE D
then GetOneLevelNode(Node, tv);
//
nLength:=nLength-Length(lp DriveName) -1;
lpDriveName:=lpDriveName+L ength(lpDr iveName)+1 ;
end;
//
FreeMem(lpBuffer);
end;
{------------------------- ---------- ---------- ------}
procedure TFormMain.tvAllDirsExpande d(Sender: TObject; Node: TTreeNode);
var ChildNode: TTreeNode;
begin
ChildNode:=Node.getFirstCh ild;
while ChildNode<>NIL do
begin
GetOneLevelNode(ChildNode, tvAllDirs);
ChildNode:=Node.GetNextChi ld(ChildNo de);
end;
end;
{------------------------- ---------- ---------- ----}
function TFormMain.GetPathFromNode( Node: TTreeNode): string;
begin
Result:='';
//
if Node=NIL
then EXIT;
//
Result:=GetPathFromNode(No de.Parent) +Node.Text ;
end;
{------------------------- ---------- ---------- -----}
procedure TFormMain.tbEXITClick(Send er: TObject);
begin
Close;
end;
{------------------------- ---------- ---------- -----}
procedure TFormMain.tbFillTreeViewCl ick(Sender : TObject);
begin
tvAllDirs.Items.Clear;
FillTreeViewWithDriveNames (tvAllDirs );
end;
{------------------------- ---------- ---------- ----}
END.
Sincerely,
Nestorua.
Here is my solution.
unit frmMain;
{-------------------------
INTERFACE
{-------------------------
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ComCtrls, ImgList, ToolWin;
type
TFormMain = class(TForm)
tvAllDirs: TTreeView;
CoolBar1: TCoolBar;
tbMain: TToolBar;
ToolButton1: TToolButton;
tbFillTreeView: TToolButton;
ToolButton3: TToolButton;
tbEXIT: TToolButton;
ToolButton5: TToolButton;
ImageList1: TImageList;
procedure tvAllDirsExpanded(Sender: TObject; Node: TTreeNode);
procedure tbEXITClick(Sender: TObject);
procedure tbFillTreeViewClick(Sender
private
function GetOneLevelNode(ParentNode
procedure FillTreeViewWithDriveNames
function GetPathFromNode(Node: TTreeNode): string;
{ Private declarations }
public
{ Public declarations }
end;
var
FormMain: TFormMain;
{-------------------------
IMPLEMENTATION
{-------------------------
{$R *.dfm}
{-------------------------
function TFormMain.GetOneLevelNode(
var lpFileName: PChar;
lpFindFileData: TWIN32FindData;
h: THandle;
HasSibling: boolean;
{---}
procedure AddChildNode;
var Node: TTreeNode;
begin
with lpFindFileData do
if ((dwFileAttributes=FILE_AT
(String(cFileName)<>'.') and (String(cFileName)<>'..'))
then
with tv.Items.AddChild(ParentNo
begin
ImageIndex:=2;
SelectedIndex:=3;
end;
end;
{---}
begin
Result:=False;
//
lpFileName:=PChar(GetPathF
h:=FindFirstFile(lpFileNam
//
if h=INVALID_HANDLE_VALUE
then EXIT
else AddChildNode;
//
HasSibling:=FindNextFile(h
while HasSibling do
begin
AddChildNode;
HasSibling:=FindNextFile(h
end;
//
ParentNode.AlphaSort;
//
Result:=ParentNode.HasChil
end;
{-------------------------
procedure TFormMain.FillTreeViewWith
var nLength,
nBufferLength: integer;
lpBuffer,
lpDriveName: PAnsiChar;
Node: TTreeNode;
begin
nBufferLength:=254;
GetMem(lpBuffer, nBufferLength+1);
nLength:=GetLogicalDriveSt
//
lpDriveName:=lpBuffer;
//
while nLength>0 do
begin
Node:=tv.Items.Add(NIL, lpDriveName);
Node.ImageIndex:=2;
Node.SelectedIndex:=3;
if GetDriveType(lpDriveName)=
then GetOneLevelNode(Node, tv);
//
nLength:=nLength-Length(lp
lpDriveName:=lpDriveName+L
end;
//
FreeMem(lpBuffer);
end;
{-------------------------
procedure TFormMain.tvAllDirsExpande
var ChildNode: TTreeNode;
begin
ChildNode:=Node.getFirstCh
while ChildNode<>NIL do
begin
GetOneLevelNode(ChildNode,
ChildNode:=Node.GetNextChi
end;
end;
{-------------------------
function TFormMain.GetPathFromNode(
begin
Result:='';
//
if Node=NIL
then EXIT;
//
Result:=GetPathFromNode(No
end;
{-------------------------
procedure TFormMain.tbEXITClick(Send
begin
Close;
end;
{-------------------------
procedure TFormMain.tbFillTreeViewCl
begin
tvAllDirs.Items.Clear;
FillTreeViewWithDriveNames
end;
{-------------------------
END.
Sincerely,
Nestorua.
ASKER
seems i have to provide some extra points :-))
ASKER
well, if all agree, i will grade as follows
raidos - 50 pts - this q raised to 50 pts
ginsonic - 25 pts - extra question
nestorua - 25 pts - extra question
igor - nothing :-)
may this ok?
meikl ;-)
raidos - 50 pts - this q raised to 50 pts
ginsonic - 25 pts - extra question
nestorua - 25 pts - extra question
igor - nothing :-)
may this ok?
meikl ;-)
You can keep my points for futhers qow ( I know that you need these ;-) ). I put my comment just to test me .
Regards,
NIck
P.S. About points sponsor problem . I think that if we contact Moondancer , she/he can move couple points from my account to your's .
Regards,
NIck
P.S. About points sponsor problem . I think that if we contact Moondancer , she/he can move couple points from my account to your's .
ASKER
well, no pints for ginsonic :-)
>I think that if we contact Moondancer , she/he can move
>couple points
could be, that SHE could help, but
i will wait to do this,
until the last moment
even as i'm kpro member my points should
be raised until 500 each month, and if i for myself has no q, it should be enough for the qows (i hope)
(thats are 20 gradings á 25 pts.)
another point would be to raise the points for a qow to 50 pts, then i will have a problem, but the qows would be still more attractive
but at the moment i leave as it is
meikl ;-)
>I think that if we contact Moondancer , she/he can move
>couple points
could be, that SHE could help, but
i will wait to do this,
until the last moment
even as i'm kpro member my points should
be raised until 500 each month, and if i for myself has no q, it should be enough for the qows (i hope)
(thats are 20 gradings á 25 pts.)
another point would be to raise the points for a qow to 50 pts, then i will have a problem, but the qows would be still more attractive
but at the moment i leave as it is
meikl ;-)
OK then . When need my support I will be glad to help you . See you on net .
I agree with no points :-)
ASKER
well raidos,
points increased to 50
nestu... (name not in mind)
an additional question will be posted for you
thanks for participating
next qow next monday,
because i was/am absent until then
meikl ;-)
points increased to 50
nestu... (name not in mind)
an additional question will be posted for you
thanks for participating
next qow next monday,
because i was/am absent until then
meikl ;-)
well I want to populat a treeview with just a list of the directorys and I want to be able to populat a listview withe the coorisponding files...how do i do that
// why do spend only 50 Points ?
Cesario