Hi!

You are very fast in replying.
Well, indeed, ShellObj frees the memory pretty much like using temporary strings. That's fascinating! All I have to do is to put anything I want to do with the ShellObj structure within the WITH context. Outside the with structure the object is already freed.
Allow me to publish the code of my testing tree view here (so other can see how easy madShell makes the stuff):
Code: Select all
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, madshell;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
procedure TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
var PaintImages, DefaultDraw: Boolean);
procedure TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private-Deklarationen }
first:boolean;
procedure addnode(node:TTreeNode; ishell:IShellObj; var level:integer);
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.addnode;
var
i:integer;
begin
inc(level);
if ishell.isfolder then begin
node:=TreeView1.Items.AddChild(node,ishell.name);
if node<>nil then begin
for i:=0 to ishell.ItemCount-1 do begin
application.ProcessMessages;
if level<3 then addnode(node,ishell.Items[i],level);
end; {for}
end; {if}
end; {if}
dec(level);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
first:=true;
end;
procedure TForm1.FormActivate(Sender: TObject);
var
level:integer;
begin
level:=0;
addnode(nil,shellobj('c:\'),level);
first:=false;
end;
function getpath(node:TTreeNode):string;
begin
result:='';
if node<>nil then begin
result:=node.Text;
while node.parent<>nil do begin
result:=node.Parent.Text+'\'+result;
node:=node.Parent;
end; {while}
result:=stringreplace(result,'\\','\',[rfReplaceAll]);
end; {if}
end;
procedure TForm1.TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
node:TTreeNode;
path:string;
begin
if button=mbright then begin
node:=TreeView1.GetNodeAt(x,y);
path:=getpath(node);
if path<>'' then shellobj(path).ShowContextMenu(handle);
end; {if}
end;
procedure TForm1.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
var PaintImages, DefaultDraw: Boolean);
var
rect:TRect;
icon:TIcon;
begin
if node<>nil then begin
rect:=node.DisplayRect(true);
with treeview1.Canvas do begin
brush.Color:=clYellow;
brush.Style:=bsSolid;
rect.Right:=rect.Right+16;
textrect(rect,rect.Left+16+2,rect.Top+2,node.text);
with ShellObj(getpath(node)) do begin
icon:=TIcon.Create;
icon.Handle:=geticon(16);
draw(rect.Left,rect.Top,icon);
icon.Free;
end; {if}
end; {with}
end; {if}
end;
end.
Well, it's only a testing project - nothing real big. It only shows 2 levels of the tree - but you can right-click to get the explorer context menu.
Now I have to take some time to study what madShell definitely performs.
You have very high knowledge of the internal structures of the Shell (but not only), and of course you did that what the ShellAPI programmers did not: Making an understandable structured object for programmers. Thanks for that very good work!
Claus.