Lazarus
Miscellaneous => Suggestions => LCL => Topic started by: kormoran on April 04, 2015, 03:51:48 pm
-
Hello, I need to calc a value for each file in a directory and show it.
TShellListView would be perfect, IF I could add another column to it... but I can't find a way. Can this be (easily) done or do I need to derive from TCustomShellListView and make my own?
Thanks :)
(edit: OOPS wrong board... plz move to Lazarus->Programming->LCL)
-
ShellListView1.Columns.Add;
ShellListView1.Column[ShellListView1.ColumnCount - 1].Caption := 'abc';
You need to derive from TShellListView or TCustomShellListView and make property Columns public. Or make a Feature Request in BugTracker in order to make it public on TCustomListView source (since Column and ColumnCount are public too).
-
Here's an example of one way to achieve this.
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, ShellCtrls, ComCtrls;
type
{ TShellListViewEx }
TShellListViewEx = class(TShellListView)
private
FNewColumn: TListColumn;
FNewColumnCaption: string;
function FileStringFunction(const aFilePath: string): string; // supply your file processing logic here
procedure PopulateWithRootEx;
public
constructor CreateEx(AOwner: TComponent; const anExtraColumn: string);
property ExColumnCaption: string read FNewColumnCaption;
end;
{ TForm1 }
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
slvEx: TShellListViewEx;
end;
var
Form1: TForm1;
implementation
uses LazLogger;
{$R *.lfm}
{ TShellListViewEx }
function TShellListViewEx.FileStringFunction(const aFilePath: string): string;
begin
if FileIsReadOnly(aFilePath) then
Result:='ReadOnly'
else Result:='Writeable';
end;
procedure TShellListViewEx.PopulateWithRootEx;
var
Files: TStringList;
i: integer;
li: TListItem;
curFilePath, filePath: string;
begin
inherited PopulateWithRoot;
if (csDesigning in ComponentState) then Exit;
if Trim(Root) = '' then Exit;
Files := TStringList.Create;
try
TCustomShellTreeView.GetFilesInDir(Root, Mask, ObjectTypes, Files);
curFilePath:=IncludeTrailingPathDelimiter(Root);
for i := 0 to Files.Count - 1 do
begin
li:=Items.FindCaption(0,Files[i],False,True,true);
if (li <> nil) then begin
filePath:=curFilePath + Files[i];
li.SubItems.Add(FileStringFunction(filePath));
end
else DebugLn('Filename %s was not in items list',[Files[i]]);
end;
finally
Files.Free;
end;
end;
constructor TShellListViewEx.CreateEx(AOwner: TComponent;
const anExtraColumn: string);
begin
inherited Create(AOwner);
FNewColumn:=Columns.Add;
FNewColumn.Caption:=anExtraColumn;
Root:='C:\'; // customise these properties appropriately
Mask:='*.*';
ObjectTypes:=[otFolders, otNonFolders];
PopulateWithRootEx;
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
slvEx:=TShellListViewEx.CreateEx(Self, 'Readonly attribute');
slvEx.Align:=alClient;
slvEx.Parent:=Self;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(slvEx);
end;
end.
-
Thank you guys, excellent answers.
(Sorry for posting in the wrong place)
-
Making a Feature Request should result, see TCustomListView source:
TShellListView = class(TCustomShellListView)
published
{ TCustomListView properties
The same as TListView excluding data properties }
property Align;
property Anchors;
property BorderSpacing;
property BorderStyle;
property BorderWidth;
// property Checkboxes;
property Color default clWindow;
// property Columns;
All they need to do is uncomment that line.
-
http://bugs.freepascal.org/view.php?id=27786
-
There is a reason why it is not published.
(See bugreport).
Bart
-
Surely there is a reasonable reason why he/she should not delete the first 3 columns.
-
Yes, and we like to not "help" people to shoot in their own foot (we're not C).
Bart
-
Blocking access to Colums property does not seem a very smart solution. Maybe a block to the first 3 would be better.
-
If all needed is to publish columns, just add this to project:
type
TShellListView = class(ShellCtrls.TShellListView)
published property Columns;
end;
-
I agree.
-
Blocking access to Colums property does not seem a very smart solution. Maybe a block to the first 3 would be better.
Yes.
Not sure how to do that though.
Any ideas?
Bart
-
First idea:
procedure AddColumn(ACaption :string);
procedure DeleteColumn(AIndex :integer);
{...}
procedure TCustomShellListView.AddColumn(ACaption :string);
begin
Columns.Add;
Column[ColumnCount - 1].Caption := ACaption;
end;
procedure TCustomShellListView.DeleteColumn(AIndex :integer);
begin
if AIndex > 2 then
Columns.Delete(AIndex);
end;
-
Still leaves the possibility to do
ShellListView1.Columns.Delete(0);
(If Columns were to be published.)
While it is possible to replace TTreeNode with a subclass (which I have done), such a mechanisme is not provided for columns.
But just introducing AddColumn and DeleteColumn might be a feasible idea.
Bart
-
Still leaves the possibility to do
ShellListView1.Columns.Delete(0);
(If Columns were to be published.)
In this case don't publish them. No need to do so if AddColumn and DeleteColumn are used.
-
Does anybody know if Delphi publishes TShellListView.Columns?
If not, do they have a method of adding/deleting columns?
If yes, can you delete all columns?
While our implementation is far from D compatible, if we implement such a thing, we might try to follow (black box aproach) the Greek.
Bart
-
I only found this in C++:
http://godcom.googlecode.com/svn/trunk/ShellControls/ShellCtrls.hpp
And it publics Columns.
public:
__fastcall virtual TCustomShellListView(Classes::TComponent* AOwner);
__fastcall virtual ~TCustomShellListView(void);
void __fastcall Back(void);
HIDESBASE void __fastcall Refresh(void);
TShellFolder* __fastcall SelectedFolder(void);
__property TShellFolder* Folders[int Index] = {read=GetFolder};
__property TShellFolder* RootFolder = {read=FRootFolder};
__property Items;
__property Columns;
I also found this unit, apparently from Delphi, and it does not public Columns.
https://github.com/Baltimore99/delphi-drag-drop/blob/master/Demos/DetailedDemo/Extra/ShellCtrls.pas
-
Oh wow, it seems that from delphi 2009 onwards the tshellxxx controls are not part of the default installation and are now published on their sourceforge project as samples on how to create controls that interact with windows shell. http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RadStudio_XE6/Object%20Pascal/VCL/ShellControls/ (http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RadStudio_XE6/Object%20Pascal/VCL/ShellControls/)
EDIT: sorry forgot that the columns seem to be public.
-
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Back;
procedure Refresh;
function SelectedFolder: TShellFolder;
property Folders[Index: Integer]: TShellFolder read GetFolder;
property RootFolder: TShellFolder read FRootFolder;
property Items;
property Columns;
Yes, thanks.
So, yes, Delphi publics Columns.
-
So, yes, Delphi publics Columns.
I made them public.
Bart