Einzelnen Beitrag anzeigen

MathiasSimmack
(Gast)

n/a Beiträge
 
#5

Gruppenzwang!

  Alt 2. Mär 2003, 19:00
Das Schwierigste zuletzt; ´s hat mich auch am meisten Nerven gekostet. Das Wichtigste hierbei ist, dass man die Gruppen (leider) selbst bilden muss. Diese Arbeit nimmt einem das System nicht ab. Die WinXP-Benutzer unter euch kennen den Effekt, den ich persönlich für recht nützlich halte. Aktiviert im Explorer einfach mal die Option "in Gruppen anzeigen".
Der Explorer sortiert die Dateien dann z.B. alfabetisch. Klickt ihr aber auf die Spalte mit der Dateigröße, dann heißen die Gruppen plötzlich "Sehr klein", "Klein", usw., und die Dateien werden entsprechend zugeordnet.

All das muss man, wie gesagt!, selbst machen. Auf der anderen Seite hat man dadurch die Freiheit, die Gruppen an die jeweilige Anwendung anzupassen. Ich erstelle als Beispiel eine einzige Gruppe, der alle Dateien zugeordnet werden. Dazu brauchen wir das Record TLVGroup, das auch erst mal initialisiert werden muss:
group.cbSize := sizeof(TLVGroup); Da wir einen Gruppennamen und eine ID für die Gruppe vergeben (müssen), sind die entsprechenden Flags zu setzen:
group.mask := LVGF_HEADER or LVGF_GROUPID; Nun kommt der Name unserer Gruppe, der als PWideChar zu übergeben ist:
Delphi-Quellcode:
group.pszHeader := pwidechar(widestring('Testgruppe'));
group.cchHeader := lstrlenW('Testgruppe');
Und die ID unserer Gruppe:
group.iGroupId := 1; Das ganze reichen wir an die List-View weiter, wobei wir als zweiten Parameter (laut PSDK: Itemindex) -1 angeben, damit die neue Gruppe an das Ende des internen Gruppenarrays der List-View gesetzt wird:
ListView_InsertGroup(lv1.Handle,-1,group); Nun müssen die Items noch irgendwie in die Gruppe rein. Ich hatte meine ersten Versuche dazu mit der Nachricht "LVM_MOVEITEMTOGROUP" (respektive "ListView_MoveItemToGroup") begonnen, aber diese Nachricht hat entweder einen vollkommen anderen Sinn, oder sie funktioniert nicht.
Tatsächlich brauchen wir das erweiterte TLVItem-Record, das man im PSDK und in der Unit "CommCtrl_Fragment.pas" (s. Anhang im ersten Beitrag) finden kann. Dieses erweiterte Record besitzt u.a. die neue Membervariable iGroupId, die wir nun brauchen. Das heißt, wir nehmen eine for-Schleife und laden nacheinander alle Items der List-View:
Delphi-Quellcode:
for i := 0 to lv1.Items.Count - 1 do begin
  // Record leeren
  ZeroMemory(@lv60,sizeof(TLVItem60));

  // Flag setzen, weil wir die Gruppen-ID ändern wollen
  lv60.mask := LVIF_GROUPID;

  // von welchem Item?
  lv60.iItem := i;

  // wie lautet die ID?
  lv60.iGroupId := 1;

  // und ab dafür
  SendMessage(lv1.Handle,LVM_SETITEM,0,LPARAM(@lv60));
end;
Bitte nicht wundern: um Probleme mit dem Originalrecord zu vermeiden, habe ich in meiner Unit den erweiterten Typ als TVLItem60 deklariert.

So, nun können wir die Gruppenansicht einschalten. Dazu gibt´s "LVM_ENABLEGROUPVIEW" bzw. die Funktion:
Delphi-Quellcode:
ListView_EnableGroupView(lv1.Handle,
  not ListView_IsGroupViewEnabled(lv1.Handle));
Diese Funktion zeigt auch gleich noch das toggeln der Ansicht mit Hilfe von "ListView_IsGroupViewEnabled" (bool-Funktion).

Ja, das war´s auch schon.
Ich bitte um Verständnis, dass ich ein paar Sachen für das nächste Update der Win32-API-Tutorials aufgehoben habe. Dort zeigt euch die neue List-View-Demo dann, wie man z.B. mehrere Gruppen erstellt, wie man prüft, ob es eine Gruppe evtl. schon gibt, und wie man die Gruppen ändert, wenn man die Items nach anderen Kriterien sortieren lässt. Wer nicht so lange warten möchte, hier die Kurzform für die alfabetische Sortierung:
  • Den Namen eines Items auslesen und nur das erste Zeichen (UPCASE!) berücksichtigen. Wenn es im Bereich von A bis Z liegt, kann eine entsprechende Gruppe erzeugt werden; alles, was außerhalb davon liegt, ist im XP-Explorer z.B. in der Gruppe "Andere" zu finden.
  • Mit Hilfe von "ListView_GetGroupInfo" (PSDK) kann man Informationen zu vorhandenen Gruppen auslesen (in dem Fall wäre nur der Header -der Gruppenname!- interessant). Die Funktion liefert -1 zurück, wenn ein Fehler auftrat, bzw. wenn die Gruppe noch nicht existiert.
  • Im Erfolgsfall sind der geplante Gruppenname (1. Zeichen des Items) und der ausgelesene Gruppenname zu vergleichen. Stimmen sie überein, existiert die Gruppe. Man verlässt die Schleife, merkt sich die ID und ordnet das aktuelle Item der gefundenen Gruppe zu. Stimmen Sie nicht überein, macht man mit Punkt #2 und der nächsten Gruppe weiter, bis man die gesuchte Gruppe findet, oder bis man alle Gruppen durchsucht hat.
  • Und jetzt wieder bei Schritt #1 beginnen und das nächste Item auslesen, usw.
Wer Delphi 7 hat, kann gern ergänzen, wie es dort funktioniert - sofern die genannten Features dort in der VCL implementiert sind.


Gruß, und viel Spaß damit.
Mathias.
  Mit Zitat antworten Zitat