ListView: Zeilen farbig darstellen



  • Hallo,

    ich hab ein Problem, ich lese bestimmte Dateien aus und schreibe diese in einen ListView mit dem ViewStyle 'vsReport'.
    Nun versuche ich je nach Eintrag die Zeilen im ListView mit einer bestimmten Farbe zu schreiben! Aber es klappt nicht. Die Farbanderungen versuche ich mit den Befehlen:

    //Hintergrund
    ListView->Canvas->Brush->Color = clFarbe;
    //Schrift
    ListView->Canvas->Font->Color = clFarbe;

    zu ändern. Kann mir vielleicht jemand sagen, warum es nicht klappt und wie es dann geht?



  • Hast du dir schon die entsprechenden Beispiele für ListBox und StringGrid in der FAQ angesehen?



  • Ahh, ich seh grad, dass das beim ListView nicht so einfach funktioniert. Aber hier findest du ein beispiel.



  • ja, hab ich! Daher hab ich ja auch den Code, für Hintergrund und Schrift. aber irgendwie funktioniert es doch nicht.
    Er führt die Befehle zwar aus, ändert aber trotzdem nicht die Farbe.



  • Sorry, aber funktioniert immer noch nicht!!



  • hi,

    schau dir mal folgenden code an:

    void __fastcall TF_Ausgang::ListViewObjektDrawItem(TCustomListView *Sender, TListItem *Item, TRect &Rect, TOwnerDrawState State)
    {
      int index = Item->Index;
    
      // markierter eintrag
      if (State.Contains(odSelected))
      {
        ListViewObjekt->Canvas->Font->Color  = clHighlightText;
        ListViewObjekt->Canvas->Brush->Color = clHighlight;
      }
    
      // normaler eintrag
      else
      {
        ListViewObjekt->Canvas->Brush->Color = clRed;
        ListViewObjekt->Canvas->Font->Color  = ListViewObjekt->Font->Color;
      }
    
      ListViewObjekt->Canvas->FillRect((TRect) Rect);
    
      int width   = Item->Left;
      Rect.Left  += 2;
    
      DrawText(ListViewObjekt->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 += ListViewObjekt->Columns->Items[col]->Width;
    
        Rect.Left  = left;
        Rect.Right = left + ListViewObjekt->Columns->Items[col + 1]->Width;
    
        if (col > 2)
        {
          Rect.Right -= 2;
          DrawText(ListViewObjekt->Canvas->Handle, Item->SubItems->Strings[col].c_str(),
                   -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_RIGHT);
        }
        else
        {
          if (col > 0)
          {
            DrawText(ListViewObjekt->Canvas->Handle, Item->SubItems->Strings[col].c_str(),
                     -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
          }
          else
          {
            Rect.Left  += 2;
            DrawText(ListViewObjekt->Canvas->Handle, Item->SubItems->Strings[col].c_str(),
                     -1, &Rect, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
          }
        }
      }
    }
    


  • Sunday: Nette funktion *grins* aber wie wärs mit etwas mehr kommentar? (-;

    -junix



  • Die Eigenschaft "Ownerdraw" des ListViews auf "true" nicht vergessen! 😃

    Was muss am Code noch verändert werden, dass Icons aus einer ImageList angezeig werden können? Durch das Owner-Draw werden die nämlich erstmal nicht mehr dargestellt ... 😕

    [ Dieser Beitrag wurde am 15.01.2003 um 10:39 Uhr von F98 editiert. ]



  • Hab die Funktion modifiziert, aber irgendwie wird zwar alles korrekt ausgeführt(fehlerfrei), doch in meinen ListView ändert sich keine Farbe, nicht mal die SubItems werden dargestellt. Was kann das sein?



  • Das dritte Zeichen von rechts in der 5. Zeile natürlich (-;

    Ne im ernst.. wenn keiner weiss was du modifiziert hast, kann auch keiner sagen was schiefläuft. Schonmal mit dem Debugger durgesteppt?

    -junix



  • Original erstellt von <Bernie>:
    nicht mal die SubItems werden dargestellt

    Die entsprechenden Columns hast du aber eingerichtet!?



  • Schon mal meinen obenstehenden Beitrag gelesen? 😞



  • Ja, Columns sind eingestellt, und OwnerDraw steht auch auf true!!

    Kann sein, dass ich das TRect Rect am Anfang falsch initialisiere!
    Wie initialisiert man es denn am besten(richtig)?



  • Du schreibst oben, Du hast die Funktion "modifiziert". Inwieweit, wenn ich fragen darf? Und zeig mal etwas Quellcode her ...



  • Hier der Code! Ich weiß halt nicht wie ich das TRect, das ich übergebe initialisiert sein muß!!

    void __fastcall TForm1::ListViewColorLine(TListItem *Item, TRect &Rect, int Auswahl)
    {
      switch(Auswahl)
      {
       case 0:
       {
         ListView->Canvas->Brush->Color = clWhite;
         ListView->Canvas->Font->Color  = clBlack;
         break;
       }
       case 1:
       {
         ListView->Canvas->Brush->Color = clWhite;
         ListView->Canvas->Font->Color  = clBlack;
         break;
       }
       case 2:
       {
         ListView->Canvas->Brush->Color = clWhite;
         ListView->Canvas->Font->Color  = clFuchsia;
         break;
       }
       case 3:
       {
         ListView->Canvas->Brush->Color = clYellow;
         ListView->Canvas->Font->Color  = clBlack;
         break;
       }
       case 4:
       {
         ListView->Canvas->Brush->Color = clRed;
         ListView->Canvas->Font->Color  = clBlack;
         break;
       }
       default:
       {
         ListView->Canvas->Brush->Color = clWhite;
         ListView->Canvas->Font->Color  = clBlack;
       }
     }
    
     ListView->Canvas->FillRect(Rect);
    
     int width   = Item->Left;
     Rect.Left  += 2;
    
     DrawText(ListView->Canvas->Handle, Item->Caption.c_str(), -1, &Rect, DT_SINGLELINE); // | DT_VCENTER | DT_LEFT
    
     Rect.Right = width;
     int left   = Rect.Left - 2;
    
     for (int z = 0; z < Item->SubItems->Count; z++)
     {
       left += ListView->Columns->Items[z]->Width;
    
       Rect.Left  = left;
       Rect.Right = left + ListView->Columns->Items[z + 1]->Width;
    
       if(z > 2)
       {
         Rect.Right -= 2;
         DrawText(ListView->Canvas->Handle, Item->SubItems->Strings[z].c_str(), -1, &Rect, DT_SINGLELINE);// | DT_VCENTER | DT_RIGHT
       }
       else
       {
         if(z > 0)
         {
           DrawText(ListView->Canvas->Handle, Item->SubItems->Strings[z].c_str(), -1, &Rect, DT_SINGLELINE);// | DT_VCENTER | DT_CENTER
         }
         else
         {
           Rect.Left  += 2;
           DrawText(ListView->Canvas->Handle, Item->SubItems->Strings[z].c_str(), -1, &Rect, DT_SINGLELINE);// | DT_VCENTER | DT_LEFT
         }
       }
     }
    
    }
    


  • Also, schau Dir doch mal richtig den Code an:

    Sunday's Code:

    void __fastcall TF_Ausgang::ListViewObjektDrawItem(TCustomListView *Sender, TListItem *Item, TRect &Rect, TOwnerDrawState State)
    {
    ...
    }
    

    Dein Code:

    void __fastcall TForm1::ListViewColorLine(TListItem *Item, TRect &Rect, int Auswahl)
    {
    ...
    }
    

    Die Übergabeparameter an die Funktion stimmen nicht überein.

    Lösung:

    In der Objektinspektor-Ansicht Deines ListViews unter Ereignisse "OnDrawItem" doppelklicken und Deinen Quellcode in den so erstellten Funktionsrumpf reinkopieren. Oder besser: erstmal den von Sunday reinbasteln und dann modifizieren.



  • Ich habe nochmal eine Frage zu ListView-OwnerDraw:

    Was muss am Code noch verändert werden, dass Icons aus einer ImageList angezeigt werden können? Im Beispiel werden die nämlich erstmal nicht mehr dargestellt ...



  • Ich gehe mal davon aus, dass du die per CopyRect o.ä. ebenfalls selbst zeichnen musst.



  • Wenn dieses Thema mal wieder aufgedeckt wird!
    Es geht auch einfacher:

    Mit CustomDrawItem. Hier muß man nichtmal OwnerDraw auf true stellen!
    Funktioniert bestimmt.

    void __fastcall TForm1::ListViewCustomDrawItem(TCustomListView *Sender,
          TListItem *Item, TCustomDrawState State, bool &DefaultDraw)
    {
       TColor BackgroundColor;
       TColor PencilColor;
    
       //Farben übergeben i ist z.B ein IntegerWert
       switch(i)
       {
         case 0:
         {
           BackgroundColor = clRed;
           PencilColor = clBlack;
           break;
         }
         case 1:
         {
           BackgroundColor = clBlue;
           PencilColor = clYellow;
           break;
         }
         default:
         {
           DefaultDraw = true;
           return;
         } 
       }
    
       //Zeilen mit gewünschter Farbe
       Sender->Canvas->Brush->Color = BackgroundCol;
       Sender->Canvas->Font->Color = PencilCol;
    }
    

    Hoff das hilft dem nächsten, der sich mit sowas auseinandersetzen muß!



  • Wie zeichnet man denn nur die 3. Zeile farbig (RowSelect=true)?
    Oder anders gefragt, wie komme ich an das Rect der dritten Zeile ran?

    Ich möchte gern immer die Zeile andersfarbig unterlegen, welche selektiert wurde, so das wenn der Focus des ListView verloren geht, man weiterhin sieht welche Zeile zuletzt ausgewählt war.


Anmelden zum Antworten