Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Listview ein Image aus ImageList zuweisen (https://www.delphipraxis.net/162075-listview-ein-image-aus-imagelist-zuweisen.html)

ereetzer 4. Aug 2011 20:38

Listview ein Image aus ImageList zuweisen
 
Nabend,

habe unten stehenden Code um Items einer Listview hinzuzufügen.

Beim Abschnitt wo ich ein Image zuweisen will krieg ich aber eine Zugriffsverletzung
"Lesen von 0000000C".

Geht das so überhaupt? Oder wie bekomme ich in Abhängigkeit der Dateiendung das Image
dem jeweiligen Item zugewiesen?

Delphi-Quellcode:
procedure TForm1.FindFileFileMatch(Sender: TObject;
  const FileInfo: TFileDetails);
begin
  with ListView1.Items.Add do
  begin
    Caption := IntToStr(ListView1.Items.Count);
    SubItems.Add(FileInfo.Location);
    SubItems.Add(FileInfo.Name);
    if LongBool(FileInfo.Attributes and FILE_ATTRIBUTE_DIRECTORY) then
      SubItems.Add('Folder')
    else
      SubItems.Add(FormatFileSize(FileInfo.Size));

      SubItems.Add(DateTimeToStr(FileInfo.ModifiedTime));
  end;

    if AnsiUpperCase(ExtractFileExt(FileInfo.Name)) = AnsiUpperCase('.mp3') then Listview1.Items.Item[ListView1.ItemIndex].ImageIndex := 0
      else
        Listview1.Items.Item[ListView1.ItemIndex].ImageIndex := -1;

  if not FindFile.Threaded then
    Application.ProcessMessages;
end;
besten Gruß
ereetzer

MGC 4. Aug 2011 21:17

AW: Listview ein Image aus ImageList zuweisen
 
Hallo,
ich habe zwar Deinen Quellcode nur sehr kurz überflogen, aber mir ist gleich Deine With-Anweisung ins Auge gestochen.

Du verwendest ListView1.Items.Add somit vor allen anderen Anweisungen in Deinem With-Block (z.B.: ListView1.Items.Add.SubItems.Add ...)

Wieso erzeugst Du kein eigenes TListItem und fügst es der ListView mit AddItem hinzu? Das würde ich persönlich sehr viel übersichtlicher finden und eröffnet Dir obendrein noch die Möglichkeit verschiedene TListItem-Klassen von TListItem abzuleiten, die dann bei einem Durchlauf des ListView-Inhalts auch unterschieden werden können.

Zitat:

Zitat von ereetzer (Beitrag 1115138)
Delphi-Quellcode:
  with ListView1.Items.Add do <- Könnte hier der Fehler sein?
  begin
    Caption := IntToStr(ListView1.Items.Count);
    SubItems.Add(FileInfo.Location);
    SubItems.Add(FileInfo.Name);
    (...)
  end;
  (...)

Ein alter Code-Snippet aus einem meiner ersten Projekte:
Delphi-Quellcode:
With ListView_DBKeysValues.Items Do
begin
  Add;
  LIndex := Count-1;
  Item[LIndex].Caption := Bezeichner;
  Item[LIndex].SubItems.Add(Wert);
end;

daywalker9 4. Aug 2011 21:37

AW: Listview ein Image aus ImageList zuweisen
 
ListView.ItemIndex wird -1 sein.


Entweder beim hinzufügen des Items
Delphi-Quellcode:
Selected:=True
oder
Delphi-Quellcode:
ListView.Items[ListView.Items.Count-1]
nutzen.

ereetzer 5. Aug 2011 06:19

AW: Listview ein Image aus ImageList zuweisen
 
Guten Morgen,

Zitat:

ListView.ItemIndex wird -1 sein.
ist leider nicht der Fall, die Zugriffsverletzung kommt nachdem der 1. Eintrag korrekt gezeichnet wurde.

@MGC:
Du hast recht, das ist sicher verbesserungswürdig, aber das verfeinern kommt später dran :-D.

Erstmal sollte es nach Möglichkeit funktionieren.

Luckie 5. Aug 2011 06:30

AW: Listview ein Image aus ImageList zuweisen
 
Der Vorschlag von MGC ist ein Schritt den Fehler zu finden. Und warum nicht gleich sauberen Code schreiben?

RWarnecke 5. Aug 2011 06:48

AW: Listview ein Image aus ImageList zuweisen
 
Ich würde die Procedure so schreiben :

Delphi-Quellcode:
procedure TForm1.FindFileFileMatch(Sender: TObject;
  const FileInfo: TFileDetails);
var
  ListItem : TListItem;
begin
  ListView1.Items.BeginUpdate;
  ListItem := ListView1.Items.Add;
  ListItem.Caption := IntToStr(ListView1.Items.Count);
  ListItem.SubItems.Add(FileInfo.Location);
  ListItem.SubItems.Add(FileInfo.Name);
  if LongBool(FileInfo.Attributes and FILE_ATTRIBUTE_DIRECTORY) then
    ListItem.SubItems.Add('Folder')
  else
  begin
    ListItem.SubItems.Add(FormatFileSize(FileInfo.Size));
    ListItem.SubItems.Add(DateTimeToStr(FileInfo.ModifiedTime));
  end;
  if AnsiUpperCase(ExtractFileExt(FileInfo.Name)) = AnsiUpperCase('.mp3') then
    ListItem.ImageIndex := 0
  else
    ListItem.ImageIndex := -1;
  ListView1.Items.EndUpdate;
  if not FindFile.Threaded then
    Application.ProcessMessages;
end;
(nicht getestet, nur runtergeschrieben)

So sollte das Befüllen der ListView funktionieren.

FredlFesl 5. Aug 2011 07:14

AW: Listview ein Image aus ImageList zuweisen
 
Um es noch sauberer zu machen:
Einen Class Helper verwenden, der das ListItem befüllt. Bei der Gelegenheit kann man dann auch gleich konsequent refaktorisieren.
Damit sollten dann die Grundregeln ordentlichen OOP einigermaßen erfüllt sein.

Delphi-Quellcode:
Type
// Es ist die Aufgabe eines TFileInfo, in meiner Applikation das richtige Icon zu liefern
  TIconIndexHelper = Class Helper For TFileInfo
    Function IsDirectory : Boolean;
    Function GetImageIndexFromFileName : Integer;
  End;

// Es ist Aufgabe eines TListItem, in meiner App sich selbst anhand eines TFileInfo zu befüllen
  TListViewItemFillFromFileInfoHelper = Class Helper For TListItem
    Procedure FillSubItemsWithNameInfo (aFileInfo : TFileInfo);
    Procedure FillContentsFromFileInfo (aFileInfo : TFileInfo);
  End;

Const
  iiNoIcon = -1;
  iiMP3Icon = 0;

Function TIconIndexHelper.GetImageIndexFromFileName : Integer;
Begin
  if AnsiUpperCase(ExtractFileExt(Name)) = AnsiUpperCase('.mp3') then
    Result := iiMP3Icon
  else
    Result := iiNoIcon;
End;

Function TIconIndexHelper.IsDirectory : Boolean;
Begin
  Result := LongBool(Attributes and FILE_ATTRIBUTE_DIRECTORY)
End;
   
Procedure TListViewItemFillFromFileInfoHelper.FillSubItemsWithNameInfo (aFileInfo : TFileInfo);
Begin
  SubItems.Add(aFileInfo.Location);
  SubItems.Add(aFileInfo.Name);
  if aFileInfo.IsDirectory then
    SubItems.Add('Folder')
  else begin
    SubItems.Add(FormatFileSize(aFileInfo.Size));
    SubItems.Add(DateTimeToStr(aFileInfo.ModifiedTime));
  end;
End;
     
Procedure TListViewItemFillFromFileInfoHelper.FillContentsFromFileInfo (aFileInfo : TFileInfo);
Begin
  Caption := IntToStr(Self.ListView.Items.Count);
  FillSubItemsWithNameInfo(aFileInfo);
  ImageIndex := aFileInfo.GetImageIndexFromFilename;
end;

...
  ListView1.Items.BeginUpdate;
  Try
    ListView1.Items.Add.FillContentsFromFileInfo (FileInfo);
  Finally
    ListView1.Items.EndUpdate;
  End;
  if not FindFile.Threaded then
    Application.ProcessMessages;
end;
Es ist natürlich 3x soviel Schreibarbeit, aber dafür übersichtlich, verständlich und leichter erweiterbar. Meine Meinung.

ereetzer 5. Aug 2011 07:25

AW: Listview ein Image aus ImageList zuweisen
 
Danke Euch allen!

@FredlFesl:
Das sieht 1. gut und obendrein so aus, das es sauber funktioniert.

Ich kann es erst am Nachmittag ausprobieren.

FredlFesl 5. Aug 2011 07:42

AW: Listview ein Image aus ImageList zuweisen
 
Ja, probiere es aus, denn ich habs nur runtergetippt.

Wenn man das aber so aufteilt und jedem Objekt/Klasse seine Aufgaben zuteilt, dann klappt es beinahe automatisch.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz