Datum in ShellListView

Rund um die LCL und andere Komponenten
Antworten
MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Datum in ShellListView

Beitrag von MacWomble »

Ist es möglich, in der ShellListView das Edit- oder Erstellungsdatum mit anzeigen zu lassen?

Wenn ja, wie - ansonsten: Was gibt es für eine Alternative?
In der IDE unter Datei-öffnen ist ja das Datum vorhanden, aber ich komme mit den IDE-Sourcen nicht klar.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Datum in ShellListView

Beitrag von theo »

Nicht direkt. Da müsstest du schon an TCustomShellListView schrauben.
"IDE unter Datei-öffnen" ist ein TOpenDialog. Den kannst du auch benutzen.
Der wird im Ggs. zu TCustomShellListView vom System zur Verfügung gestellt, sieht dafür aber auf verschiedenen Systemen anders aus.

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Datum in ShellListView

Beitrag von MacWomble »

Danke, ich habe es befürchtet. Da ich die Liste im Programm benötige, nutzt mir der Open-Dialog leider nicht viel.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Datum in ShellListView

Beitrag von wp_xyz »

Ich denke, das ist gar nicht so wild... Das folgende ist aber nicht getestet, aber schau dir einfach den Quellcode von TShellListView an.

  1. Leite von TCustomShellListView eine neue Klasse ab, z.B. TExtShellListView
  2. Überschreibe Create und füge weitere Spalten hinzu

    Code: Alles auswählen

    constructor TExtShellListView.Create(Sender: TObject);
    begin
      inherited;
      Columns.Add('Datum');
      OnFileAdded := @FileAdded;
    end;
  3. Die Liste wird in PopulateWithRoot gefüllt. Nach dem Hinzufügen eines jeden Items wird ein Event OnFileAdded generiert, dem der betreffende ListItem mitgegeben ist. Du musst nur noch das Dateidatum bestimmen. z.B. FileAge(dateiname) und an die SubItems des Listitem anhängen.

    Code: Alles auswählen

    procedure TExtShellListView.FileAdded(Sender: TObject; NewItem: TListItem);
    var
      dt: TDateTime;
    begin
      FileAge(IncludeTrailingPathDelimiter(FRoot) + NewItem.Caption, dt);
      NewItem.SubItems.Add(FormatDateTime(dt));
    end;
  4. Veröffentliche die Properties von TShellListview, die du brauchst. Falls du wieder ein OnFileAdded-Ereignis zur Verfügung stellem willst, musst du es neu deklarieren und in FileAdded aufrufen.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Datum in ShellListView

Beitrag von wp_xyz »

Ich hab's jetzt durchgespielt und bin noch auf ein paar Stolpersteine gestoßen, vor allem weil der Autor die "glorreiche" Idee hatte, eine automatische Anpassung der Breite der drei Spalten an die Control-Breite einzubauen, die man nicht abschalten kann - bei 4 Spalten wird's dann eng... (Das wäre wieder einen Bug-Report wert).

In der Anlage findest du eine kleines Quick-and-dirty Beispiel, es hat einige Seiteneffekte, nämlich dass die Ereignisse OnFileAdded und OnResize zwar noch zur Verfügung stehen, aber nicht mehr funktioneren (OnResize) bzw. die Funktion der neuen Spalte behindern (OnFileAdded). Das zu beheben wäre wesentlich mehr Aufwand gewesen. Oder weiß jemand, wie man bei einer virtuallen Methode die von den Großeltern geerbte Methode aufruft, also quasi ein "inherited inherited"? Das würde wahrscheinlich das OnResize einfach fixen lassen.
Dateianhänge
ExtShellListview.png
ShellListView_new_column.zip
(2.31 KiB) 115-mal heruntergeladen
Zuletzt geändert von wp_xyz am Sa 26. Aug 2017, 00:14, insgesamt 1-mal geändert.

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Datum in ShellListView

Beitrag von MacWomble »

Das sieht ja richtig gut aus !
Herzlichen Dank für Deine Bemühungen !
:D

Ich probiere das morgen mal in meine Anwendung zu implementieren.

Was ich nicht verstehe ist, dass es das im (Standard) FileListView nicht bereits gibt.
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Datum in ShellListView

Beitrag von theo »

Statt einer Ableitung für den Hausgebrauch würde man für solche Dinge besser einen Patch auf TCustomShellListView machen.
Hatte ich auch gemacht für "OnFileAdded". https://bugs.freepascal.org/view.php?id=27422
Deshalb können das jetzt alle benutzen. :wink:

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Datum in ShellListView

Beitrag von braunbär »

wp_xyz hat geschrieben:Oder weiß jemand, wie man bei einer virtuallen Methode die von den Großeltern geerbte Methode aufruft, also quasi ein "inherited inherited"? Das würde wahrscheinlich das OnResize einfach fixen lassen.

Vorvorvorfahr(self).create sollte im Create des Typs funktionieren, oder nicht? Create ist ja im Gegensatz zu destroy statisch, wenn ich mich nicht irre.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Datum in ShellListView

Beitrag von wp_xyz »

theo hat geschrieben:Statt einer Ableitung für den Hausgebrauch würde man für solche Dinge besser einen Patch auf TCustomShellListView machen.

Das ist schon klar, aber so einen halbseidenen Patch würde ich nicht akzeptieren. Ein richtiger Patch müsste das Problem grundsätzlicher angehen und dem Benutzer eine Schnittstelle zur Verfügung stellen, beliebige Spalten hinzuzufügen; auch die nicht abschaltbare Spaltenbreitenautomatik muss weg. Mein Versuch war eigentlich eher als Motivation gedacht, dass die Leute einmal in den Quellcode schauen sollten, um Ideen für die Lösung ihrer Probleme zu bekommen - auch wenn das nicht so ausgedrückt war.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Datum in ShellListView

Beitrag von theo »

wp_xyz hat geschrieben:
theo hat geschrieben:Statt einer Ableitung für den Hausgebrauch würde man für solche Dinge besser einen Patch auf TCustomShellListView machen.

Das ist schon klar, aber so einen halbseidenen Patch würde ich nicht akzeptieren. Ein richtiger Patch müsste das Problem grundsätzlicher angehen und dem Benutzer eine Schnittstelle zur Verfügung stellen, beliebige Spalten hinzuzufügen; auch die nicht abschaltbare Spaltenbreitenautomatik muss weg. Mein Versuch war eigentlich eher als Motivation gedacht, dass die Leute einmal in den Quellcode schauen sollten, um Ideen für die Lösung ihrer Probleme zu bekommen - auch wenn das nicht so ausgedrückt war.


Mein Einwand sollte ja keine Kritik sein, sondern eine Motivation, genau das zu machen was du beschreibst.
Als Bonus braucht man sich dann nicht mehr mit der begrenzten Eingriffsmöglichkeit einer Ableitung herumzuschlagen.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Datum in ShellListView

Beitrag von wp_xyz »

braunbär hat geschrieben:
wp_xyz hat geschrieben:Oder weiß jemand, wie man bei einer virtuallen Methode die von den Großeltern geerbte Methode aufruft, also quasi ein "inherited inherited"? Das würde wahrscheinlich das OnResize einfach fixen lassen.

Vorvorvorfahr(self).create sollte im Create des Typs funktionieren, oder nicht? Create ist ja im Gegensatz zu destroy statisch, wenn ich mich nicht irre.

Ich meine die Methode Resize. Die von TCustomShellListView geerbte Methode ruft zuerst die nun von TControl geerbte Methode auf und führt dann die automatische Spaltenbreitenanpassung für 3 Spalten durch. Ich müsste die Spaltenbreitenanpassung auf 4 Spalten erweitern. Dazu müsste ich das von TControl, nicht von TCustomShellListview geerbte Resize aufrufen und dann meinen speziellen Code anfügen. (das von TCustomShellListView geerbte Resize führt zu heftigem Flackern und Hängen des Programms). Nur: wie geht das? "Inherited Inherited" wird nicht akzeptiert, genausowenig wie "TControl(Self).Resize"

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Datum in ShellListView

Beitrag von MacWomble »

Ich have mal begonnen, das in Shellcontrols.pas zu implementieren (funktioniert, aber noch nicht fertig)
Änderungen sind mit //CTR markiert:

Code: Alles auswählen

 
constructor TCustomShellListView.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
 
  // Initial property values
  ViewStyle := vsReport;
  ObjectTypes := [otNonFolders];
 
  Self.Columns.Add;
  Self.Columns.Add;
  Self.Columns.Add;
  Self.Columns.Add//CTR
  Self.Column[0].Caption := sShellCtrlsName;
  Self.Column[1].Caption := sShellCtrlsSize;
  Self.Column[2].Caption := sShellCtrlsType;
  Self.Column[3].Caption := 'Date';   //CTR - has to be declared elsewhere
 
  // Initial sizes, necessary under Windows CE
  Resize;
end;
 
destructor TCustomShellListView.Destroy;
begin
  ShellTreeView := nil;
  inherited Destroy;
end;
 
procedure TCustomShellListView.PopulateWithRoot();
var
  i: Integer;
  Files: TStringList;
  NewItem: TListItem;
  CurFileName, CurFilePath: string;
  CurFileSize: Int64;
  CurFileDate:  TDateTime; //CTR
begin
  // avoids crashes in the IDE by not populating during design
  if (csDesigning in ComponentState) then Exit;
 
  // Check inputs
  if Trim(FRoot) = '' then Exit;
 
  Files := TStringList.Create;
  try
    Files.OwnsObjects := True;
    TCustomShellTreeView.GetFilesInDir(FRoot, FMask, FObjectTypes, Files);
 
    for i := 0 to Files.Count - 1 do
    begin
      NewItem := Items.Add;
      CurFileName := Files.Strings[i];
      CurFilePath := IncludeTrailingPathDelimiter(FRoot) + CurFileName;
      // First column - Name
      NewItem.Caption := CurFileName;
      // Second column - Size
      // The raw size in bytes is stored in the data part of the item
      CurFileSize := FileSize(CurFilePath); // in Bytes
      NewItem.Data := Pointer(PtrInt(CurFileSize));
      if CurFileSize < 1024 then
        NewItem.SubItems.Add(Format(sShellCtrlsBytes, [IntToStr(CurFileSize)]))
      else if CurFileSize < 1024 * 1024 then
        NewItem.SubItems.Add(Format(sShellCtrlsKB, [IntToStr(CurFileSize div 1024)]))
      else
        NewItem.SubItems.Add(Format(sShellCtrlsMB, [IntToStr(CurFileSize div (1024 * 1024))]));
      // Third column - Type
      NewItem.SubItems.Add(ExtractFileExt(CurFileName));
      // CTR Fourth column - Date - inserted next two lines
      FileAge(CurFilePath, CurFileDate);
      NewItem.SubItems.Add(FormatDateTime('DD.MM.YYYY  hh:mm', CurFileDate));
 
      if Assigned(FOnFileAdded) then FOnFileAdded(Self,NewItem);
    end;
    Sort;
  finally
    Files.Free;
  end;
end;
 
procedure TCustomShellListView.Resize;
begin
  inherited Resize;
  {$ifdef DEBUG_SHELLCTRLS}
    debugln(':>TCustomShellListView.HandleResize');
  {$endif}
 
  // The correct check is with count,
  // if Column[0] <> nil then
  // will raise an exception
  if Self.Columns.Count < 4 then Exit;     //CTR 3 durch 4 ersetzt
 
  // If the space available is small,
  // alloc a larger percentage to the secondary
  // fields
  if Width < 400 then
  begin
    Column[0].Width := (30 * Width) div 100//CTR
    Column[1].Width := (25 * Width) div 100;
    Column[2].Width := (25 * Width) div 100;
    Column[3].Width := (30 * Width) div 100//CTR
  end
  else
  begin
    Column[0].Width := (40 * Width) div 100//CTR
    Column[1].Width := (15 * Width) div 100;
    Column[2].Width := (15 * Width) div 100;
    Column[3].Width := (25 * Width) div 100;   //CTR
  end;
 
  {$ifdef DEBUG_SHELLCTRLS}
    debugln([':<TCustomShellListView.HandleResize C0.Width=',
     Column[0].Width, ' C1.Width=', Column[1].Width,
     ' C2.Width=', Column[2].Width]);
  {$endif}
end;
 
function TCustomShellListView.GetPathFromItem(ANode: TListItem): string;
begin
  Result := IncludeTrailingPathDelimiter(FRoot) + ANode.Caption;
end;
 
procedure Register;
begin
  RegisterComponents('Misc',[TShellTreeView, TShellListView]);
end;
 
 
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Datum in ShellListView

Beitrag von wp_xyz »

Genau, so ähnlich hatte ich mir das auch gedacht.

Ein paar Ideen noch:
Wenn du dir den Quellcode von TCustomShellTreeView.GetFilesInDir ansiehst, wirst du bemerken, dass der per FindFirst/FindNext gefundene SearchRec in the Objects der Stringliste Files gepackt ist. Im SearchRec steht aber schon alles mögliche an Informationen, z.B. die Dateigröße und das Dateidatum. Das heißt, man muss FileSize() und FileAge() nicht separat aufrufen (das ging in meiner Lösung nicht, weil die Routine PopulateWithRoot von außen nicht zugänglich ist), denn diese machen nichts anderes als ein zusätzliches, unnötiges FindFirst().

Dann würde ich mir einen Typ TShellListViewColumnOptions = set of (coSize, coType, coDate) definieren, mit dem man festlegen kann, welche Spalten neben dem immer sichtbaren Dateinamen angezeigt werden. Denn wenn die geänderte Komponente in Lazarus aufgenommen werden soll, muss sie sich in der Regel so verhalten wie die alte. Und ich könnte mir vorstellen, dass es Benutzer gibt, deren Formularlayout geändert werden muss, wenn plötzlich 4 statt 3 Spalten in der Listview sind. Daher sollte die Option coDate standardmäßig abgewählt sein.

Ins Feld Data des Parameters NewItem, der dem Ereignis OnFileAdded mitgegeben wird, sollte man eigentlich einen Zeiger auf den SearchRecord einhängen, nicht nur die Dateigröße. Aber das bricht den Code von Benutzern, die das schon so wie's jetzt ist verwenden. Wahrscheinlich wäre es sinnvoller, ein neues Event zu deklarieren, z.B. OnAddFile, und das alte als "deprecated" zu kennzeichnen.

Die automatische Berechnung der Spaltenbreite müsste man mit sowas wie "AutoColWidths" abschaltbar machen. Nur, wie kann der Benutzer dann die Spaltenbreite eingeben? Man könnte die Eigenschaft Columns wieder als published deklarieren, dann hätte der Benutzer volle Kontrolle. Insbesondere könnte er über das Dateidatum hinaus noch weitere Spalten einfügen. Die Zelldaten würden dann im OnAddFile (oderOnFileAdded)-Event zugewiesen. Allerdings würde das auch bedeuten, dass man prüfen muss, ob er nicht die eingebauten Spalten gelöscht hat oder an einen anderen Index verschoben hat -- das könnte etwas aufwendig werden, das naheliegende Feld Tag darf man hier nicht verwenden - es ist für den Benutzer reserviert.

MacWomble
Lazarusforum e. V.
Beiträge: 999
Registriert: Do 17. Apr 2008, 01:59
OS, Lazarus, FPC: Mint 21.1 Cinnamon / FPC 3.2.2/Lazarus 2.2.4
CPU-Target: Intel i7-10750 64Bit
Wohnort: Freiburg

Re: Datum in ShellListView

Beitrag von MacWomble »

Da ich im Moment zeitlich wahrscheinlich nicht dazu komme vermerke ich hier für später, was ansonsten auch noch berücksichtigt werden sollte:
(Zuzüglich der Sachen im vorherigen Post von wp_xyz und den Kommentaren im Quellcodeteil)

Betroffene Dateien: lcl/ShellCtrls, lcl/LCLStrConsts

1. Property für Datumsformat
2. Properties ShowSize, ShowType, ShowDate
3. Erweiterung des Sort-Properties um Date
4. Properties für Width von File, Size, Type, Date

Ideen und/oder Anregungen gerne hier posten!

Anmerkung: Ich habe bisher noch nie mit Komponentenentwicklung zu tun gehabt und muss mich da wohl erst etwas einarbeiten.
Da ich einen Abgabetermin für meine Software einzuhalten habe, fehlt mir in den kommenden Wochen hierzu vermutlich die notwendige Zeit.
Sollte also jemand Lust verspüren, sich der Aufgabe annehmen zu wollen bzw. mich hierbei zu unterstützen - nur zu :twisted: ;-)
Alle sagten, dass es unmöglich sei - bis einer kam und es einfach gemacht hat.

Antworten