Blauen Auswahlbalken per Code bewegen

iZeilenIndex = 5; // Zeile in die der Balken rutschen soll, die Zeile muß natürlich auch vorhanden sein, sonst gibts Fehler
lvTestFunctions->HideSelection = false;
lvTestFunctions->SetFocus(); // wichtig, sonst ist evtl. der Balken nur grau

lvTestFunctions->Selected = lvTestFunctions->Items->Item[iZeilenIndex];
lvTestFunctions->Selected->Focused = true;
lvTestFunctions->Selected->MakeVisible(false);

ListView Colums ASC/DESC über Klick auf den Header des LV sortieren

  • ViewStyle = vsReport sein // im OI einstellen
  • ColumnClick = true // im OI einstellen
  • SortType = stData // im OI einstellen
  • *.h
private:

int ColumnToSort;
bool bSortASC;
  • *.cpp
// im Konstruktor der Form Variablen initialisieren
void __fastcall TfrmMain::TfrmMain()
{
    ColumnToSort = 1; // 1. zu sortierende Spalte, z.B. Name
    bSortASC = true;  // ASC sortieren
}

// OnColumnCompare Methode des LV, wird nur ausgeführt, wenn SortType == stData
void __fastcall TfrmMain::lvWindowsCompare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &Compare)
{
    switch (ColumnToSort)
    {
          // Spalte 1 beinhaltet beispielsweise Strings
          case 0 : { Compare = bSortASC ? AnsiCompareStr(Item1->Caption, Item2->Caption) : -AnsiCompareStr(Item1->Caption, Item2->Caption);
                     break; }
          // Spalte 2 ist beispielsweise mit Zahlen gefüllt und würde mit AnsiCompareStr() falsch sortiert, daher Hilfsfunktion IntCompare (s.u.)
          case 1 : { Compare = bSortASC ? IntCompare(Item1->SubItems->Strings[ColumnToSort - 1].ToInt(), Item2->SubItems->Strings[ColumnToSort - 1].ToInt()) : -IntCompare(Item1->SubItems->Strings[ColumnToSort - 1].ToInt(), Item2->SubItems->Strings[ColumnToSort - 1].ToInt());
                     break; }
          // restl. Spalten (-> 2) mit Subitems sind wieder mit Strings gefüllt
          default : { Compare = bSortASC ? AnsiCompareStr(Item1->SubItems->Strings[ColumnToSort - 1], Item2->SubItems->Strings[ColumnToSort - 1]) : -AnsiCompareStr(Item1->SubItems->Strings[ColumnToSort - 1], Item2->SubItems->Strings[ColumnToSort - 1]); }
    }
}

// OnColumnClick Methode des LV
void __fastcall TfrmMain::lvWindowsColumnClick(TObject *Sender, TListColumn *Column)
{
    if (ColumnToSort == Column->Index)
    {
       bSortASC = !bSortASC;   // Sortorder ASC/DESC durch Klicken auf den Header umschalten
    }
    else
    {
        bSortASC = true; // am Anfang oder bei Klicken auf eine andere Spalte immer true setzen
    }

    ColumnToSort = Column->Index; // geklickte Spalte merken

    lvWindows->AlphaSort();       // LV sortieren
}

// Hilfsfunktion zum Vergleich zweier int-Werte
int __fastcall TfrmMain::IntCompare(int i1, int i2)
{
    return i1 == i2 ? 0 : i1 < i2 ? -1 : 1;
}

alle selektierten Elemente eines Listviews ermitteln

// Eigenschaft Multiselect sollte 'true' sein 
void __fastcall TfrmSysConfig::btnDoSmthClick(TObject *Sender)
{
    TListItem *SelItem = ListView1->Selected;
    TItemStates selected = TItemStates() << isSelected;

    AnsiString sTempText;

    if (SelItem) // wenn überhaupt eins ausgewählt wurde
    {
        while (SelItem) // nur die selektierten werden herausgesucht
        {
            sTempText = SelItem->Caption;

            ShowMessage(sTempText);

            // nächstes selektiertes suchen
            SelItem = ListView1->GetNextItem(SelItem, sdAll, selected);
        }
    }
}

Listview-Items selbstdefinierte Objekte zuordnen

  • als erstes sollte man sich eine Klasse definieren, die die Speicher-Objekte beschreibt (in einer Header-Datei)
class TListItemData
{
    public:

    // Konstruktor der Klasse
    TListItemData(){};

    // Objektvariablen
    int iId;
    AnsiString sName;
};
  • Um ein Objekt einem Listview-Item zuzuordnen muss man folgendermaßen vorgehen
// Zeiger für das Listitem definieren
TListItem *ListItem;

// neues Listitem hinzufügen
ListItem = ListView->Items->Add();
ListItem->Caption = &quot;Eintrag&quot;;

// neues Datenobjekt erzeugen
TListItemData *ItemData = new TListItemData();
ItemData->iId = 1;
ItemData->sName = &quot;Horst&quot;;

// Datenobjekt dem Listitem zuordnen (Zeiger übergeben)
ListItem->Data = ItemData;
  • Der Zugriff auf ein solches Objekt kann wie folgt realisiert werden
void __fastcall TForm1::ListViewClick(TObject *Sender)
{
    if (ListView->Selected)
    {
        TListItemData *TempItem;

        // Datenzeiger vom akt. Listviewelement holen
        TempItem = (TListItemData*)ListView->Items->Item[i]->Data;

        // Wenn ein gültiger Zeiger vorhanden (!= NULL)
        if (TempItem)
        {
            Label1->Text = IntToStr(ItemData->iId);
            Label2->Text = ItemData->sName;
        }
        else // sonst Fehlermeldung
        {
            ShowMessage(&quot;Objekt nicht verfügbar!&quot;);
        }
    }
}
  • naturlich darf man das Löschen der so zugewiesenen Speicherobjekte nicht vergessen, dazu dient folgende Funktion
void __fastcall TForm1::DeleteAllItemData()
{
    TListItemData *TempItem;

    // Alle Items->Data des Listviews löschen
    for (int i=0; i<ListView->Items->Count; i++)
    {
        // Zeiger auf das akt. ListItem->Data->Objekt holen
        TempItem = (TListItemData*)ListView->Items->Item[i]->Data;
        if (TempItem)
        {
            // alle Zeiger und Objekte löschen
            ListView->Items->Item[i]->Data=NULL;
            delete TempItem;
            TempItem = NULL;
        }
    }
}

Listview einfärben und formatieren

// Ownerdraw des  ListViews muss auf  true gestellt werden
void __fastcall TF_Ausgang::ListView1DrawItem(TCustomListView *Sender, TListItem *Item, TRect &Rect, TOwnerDrawState State)
{
    // markierter eintrag
    if (State.Contains(odSelected))
    {
        ListView1->Canvas->Font->Color = clHighlightText;
        ListView1->Canvas->Brush->Color = clHighlight;
    }
    else // normaler eintrag
    {
        ListView1->Canvas->Brush->Color = clRed;
        ListView1->Canvas->Font->Color = ListView1->Font->Color;
    }

    ListView1->Canvas->FillRect((TRect) Rect);

    int width = Item->Left;
    Rect.Left += 2;

    DrawText(ListView1->Canvas->Handle, Item->Caption.c_str(), -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_LEFT);

    Rect.Right = width;
    int left = Rect.Left - 2;

    for (int col = 0; col < Item->SubItems->Count; col++)
    {
        left += ListView1->Columns->Items[col]->Width;
        Rect.Left = left;
        Rect.Right = left + ListView1->Columns->Items[col + 1]->Width;

        if (col -> 2)
        {
            Rect.Right -= 2;
            DrawText(ListView1->Canvas->Handle, Item->SubItems->Strings[col].c_str(), -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_RIGHT);
        }
        else
        {
            if (col -> 0)
            {
                DrawText(ListView1->Canvas->Handle, Item->SubItems->Strings[col].c_str(), -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
            }
            else
            {
                Rect.Left += 2;
                DrawText(ListView1->Canvas->Handle, Item->SubItems->Strings[col].c_str(), -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
            }
        }
    }
}
  • oder einfacher über die Methode CustomDrawItem
void __fastcall TForm1::ListView1CustomDrawItem(TCustomListView *Sender, TListItem *Item, TCustomDrawState State, bool &DefaultDraw)
{
    Sender->Canvas->Brush->Color = clInfoBk;
    Sender->Canvas->Font->Color = clBlack;
}

Daten aus einer Datenbank-Tabelle in einem ListView anzeigen

  • Im Beispiel liegen die für den Datenbankzugriff benötigten Komponenten (TDatabase, TQuery) auf einem DataModul (TDataModule).
#include "DataModule.h"

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    SqlQuery(true, "SELECT * FROM TabellenName"); // Daten holen, siehe Beispiel weiter oben

    ListView->Items->Clear(); // Listviel erstmal leeren

    // alle Datensätze aus der Query in das ListView holen
    for (int i=0; i<DataModule->SQLQuery->RecordCount; i++)
    {
        ListItem = ListView->Items->Add();

        // fiktiven Namen und Alter ins Listview übertragen
        ListItem->Caption = DataModule->SQLQuery->FieldByName("name")->AsString);
        ListItem->SubItems->Add(DataModule->SQLQuery->FieldByName("alter")->AsString);

        // zum nächsten Datensatz springen
        DataModule->SQLQuery->Next();
    }
}

Zeilen in ein Listview einfügen

  • im Objektinspektor sollte ViewStyle = vsReport und RowSelect = true gesetzt sein
  • evtl. sollten im Objektinspektor auch unter Columns Spalten vordefiniert werden (hier im Beispiel sind es 3)
void __fastcall TfrmMain::Button1Click(TObject *Sender)
{
    TListItem *ListItem; // als erstes einen Zeiger auf ein Listitem definieren
    ListView->Items->Clear();

    ListItem = ListView->Items->Add(); // neues Item hinzufügen
    ListItem->Caption = &quot;Text1&quot;; // ItemText festlegen
    ListItem->SubItems->Add(&quot;Text2&quot;); // 2 Subitems hinzufügen
    ListItem->SubItems->Add(&quot;Text3&quot;);
}