Zeile einer Listbox blau hinterlegen



  • Hallo,

    nutze den Code aus dem C++ Forum.
    leider ändern sich nur die Farben be einem " Click " auf die Zeile.
    Hatte mir vorgestellt, das die Farbe sich beim Cursor auf die Zeile ändert.

    void __fastcall TFrameListbox::ListBox1DrawItem(TWinControl *Control,
          int Index, TRect &Rect, TOwnerDrawState State)
    {
    int i=0;
    //
      if(State.Contains(odSelected))
      {
        ListBox1->Canvas->Brush->Color = LBColors[0];   // Hintergrundfarbe
        ListBox1->Canvas->Font->Color = LBColors[4];      // Textfarbe
      }
      else
      {
        ListBox1->Canvas->Brush->Color = LBColors[4];     // Textfarbe
        ListBox1->Canvas->Font->Color = LBColors[3];      //Hintergrundfarbe
      }
      // Hintergrund zeichnen
      ListBox1->Canvas->FillRect(Rect);
      // Text zeichnen
      ListBox1->Canvas->TextRect(Rect, Rect.Left, Rect.Top,
                                 ListBox1->Items->Strings[Index]);
        i = Index;
    
      if(State.Contains(odFocused))
        {
        ListBox1->Canvas->DrawFocusRect(Rect);
        }
    //
      Label1->Caption = IntToStr(MousePosIndex);
      Label2->Caption = IntToStr(i);
    }
    //---------------------------------------------------------------------------
    

    wer kann mir helfen?

    Gruß Siegfried 😞



  • Hallo

    ich glaube das beste ist eine Ableitung von TListBox, um den Effekt zu erzeugen.
    Zuerst erstellst du eine Klasse dafür, wie hier in diesem Beispiel
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-112679-and-start-is-0.html
    nur das du statt ComboBox immer ListBox schreibst und die automatisch erstellten Dateien stattdessen anders erweiterst.
    Headerdatei ListBoxEx.h :

    ...
    private:
    	void __fastcall wmMouseMove(TMessage& Msg);
    	void __fastcall cmMouseLeave(TMessage& Msg);
            int iLastIndex; // interner Sppeicher für das letzte mit der Maus überfahrene Item
            TOwnerDrawState GetItemState(int CurrIndex);
    
    protected:
      BEGIN_MESSAGE_MAP
        MESSAGE_HANDLER(WM_MOUSEMOVE, TMessage, wmMouseMove);
        MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, cmMouseLeave);
      END_MESSAGE_MAP(TListBox)
    
      virtual void __fastcall DrawItem(int Index, const TRect &Rect, TOwnerDrawState State);
    
    public:
    ...
    

    Implementationsdatei ListBoxEx.cpp :

    void __fastcall TListBoxEx::DrawItem(int Index,
          const TRect &Rect, TOwnerDrawState State)
    {
      if(State.Contains(odSelected))
      {
        Canvas->Brush->Color = clHighlight;   // Hintergrundfarbe
        Canvas->Font->Color = clHighlightText;      // Textfarbe
      }
      else
      {
        Canvas->Brush->Color = clWindow	;     // Textfarbe
        Canvas->Font->Color = clMenuText	;      //Hintergrundfarbe
      }
    
      // Hier wird jetzt das gerade von der Maus überfahrene Item anders gezeichnet
      if (iLastIndex == Index)
      {
        Canvas->Font->Color = clRed;
        }
    
      // Hintergrund zeichnen
      Canvas->FillRect(Rect);
      // Text zeichnen
      Canvas->TextRect(Rect, Rect.Left +2, Rect.Top,
                                 Items->Strings[Index]);
    
      if(State.Contains(odFocused))
        {
        Canvas->DrawFocusRect(Rect);
        }
    }
    //---------------------------------------------------------------------------
    
    // Ermittelt den OwnerDrawState für ein Item
    TOwnerDrawState TListBoxEx::GetItemState(int CurrIndex)
    {
      TOwnerDrawState State = TOwnerDrawState();
      if (ItemIndex == CurrIndex)
        State << odSelected;
      return(State);
      }
    
    void __fastcall TListBoxEx::wmMouseMove(TMessage& Msg)
    {
      TPoint CursorPoint; // aktueller Punkt des Mauscursors
      GetCursorPos(&CursorPoint); // Cursor ermitteln
      CursorPoint = ScreenToClient(CursorPoint); // Cursor auf dieses Control umrechnen
      int CursorIndex = ItemAtPos(CursorPoint, true); // Item unter Cursor ermitteln
    
      // Wenn Item unter Cursor vorhanden, dieses neu zeichnen
      if (CursorIndex != -1)
      {
        TRect Rect = ItemRect(CursorIndex);
        DrawItem(CursorIndex, Rect, GetItemState(CursorIndex));
        }
    
      // Wenn vor dem Aufruf ein anderes Item hervorgehoben war, dieses
      // ermitteln und neu ohne Vorhebung zeichnen
      if ((iLastIndex != CursorIndex) && (iLastIndex > -1))
      {
        TRect Rect = ItemRect(iLastIndex);
        int Buffer = iLastIndex;
        iLastIndex = CursorIndex;
        DrawItem(Buffer, Rect, GetItemState(Buffer));
        }
      iLastIndex = CursorIndex; // neuen Index übernehmen
      }
    //---------------------------------------------------------------------------
    
    void __fastcall TListBoxEx::cmMouseLeave(TMessage& Msg)
    {
      if (iLastIndex == -1) return; // Wenn keine Vorhebung, beenden
    
      // Item ohne Vorhebung neu zeichnen und Index zurücksetzen
      TRect Rect = ItemRect(iLastIndex);
      int Buffer = iLastIndex;
      iLastIndex = -1;
      DrawItem(Buffer, Rect, GetItemState(Buffer));
      }
    //---------------------------------------------------------------------------
    
    __fastcall TListBoxEx::TListBoxEx(TComponent* Owner)
            : TListBox(Owner)
    {
      iLastIndex = -1; // Startwert
    }
    //---------------------------------------------------------------------------
    

    bis bald
    akari



  • Hallo,

    muß alles ausprobieren.

    vorerst vielen Dank

    Gruß Siegfried



  • Hallo,

    hat funktioniert.
    kann man nachträglich den Code abändern und die Komponente updaten ?

    Gruß Siegfried



  • Hallo

    klar.
    du öffnest das erstellte Package (Package_ListBoxEx.bpk), änderst den Code und compilierst und installierst das Package neu. Die alte Version wird dann ersetzt.

    bis bald
    akari



  • Hallo,

    hat auch funktioniert.
    Habe aber noch ein Problem. Habe im OI die Schrift auf Fett eingestellt. Wenn ich mit der Maus über die Zeilen fahre, wandelt sich der Text in normal um.

    wo muß ich noch eine Änderung durchführen ?

    Gruß Siegfried



  • Hallo

    einfach die Funktion DrawItem so erweitern

    void __fastcall TListBoxEx::DrawItem(int Index,
          const TRect &Rect, TOwnerDrawState State)
    {
      Canvas->Font = Font; // übernimmt den Font des Controls zum Darstellen
      ...
    

    bis bald
    akari



  • Hallo,

    funktioniert, so wie ich es wollte.

    Danke !!!

    Gruß Siegfried 👍 👍 👍



  • Hallo @akari

    die Komponente funktioniert gut.
    Jetzt wollte ich "OnMouseMove" zusätzlich nutzen. Klappt leider nicht.
    OnMouseDown und OnMouseUp klappt.

    brauche Hilfe!

    Gruß Siegfried 😞



  • Hallo

    liegt daran, das in der abgeleiteten Komponente ja die MouseMove-Botschaft abgefangen wird. Alles was du tun must, ist den OnMouseMove-Event selber auszulösen

    void __fastcall TListBoxEx::wmMouseMove(TMessage& Msg)
    {
      ...
      if (OnMouseMove) OnMouseMove(this, TShiftState(), 0, 0);
      }
    

    DIe letzten drei Parameters kannst du auch noch bestimmen, u.a. aus den Message-Parametern.

    /Edit : Oder besser der Vorschlag von Jansen.

    bis bald
    akari



  • In den MessageHandlern fehlt das Dispatch().
    Siehe auch den entsprechenden FAQ-Eintrag im Abschnitt "System".



  • Hallo,
    Danke an alle für die Hilfe.

    void __fastcall TListBoxEx::wmMouseMove(TMessage& Msg)
    {
    // OnMouseMove Ereignis auswerten
    if (OnMouseMove) OnMouseMove(this, TShiftState(), 0, 0);
    //
    //
      TPoint CursorPoint; // aktueller Punkt des Mauscursors
      GetCursorPos(&CursorPoint); // Cursor ermitteln
      CursorPoint = ScreenToClient(CursorPoint); // Cursor auf dieses Control umrechnen
      int CursorIndex = ItemAtPos(CursorPoint, true); // Item unter Cursor ermitteln
    
      // Wenn Item unter Cursor vorhanden, dieses neu zeichnen
      if (CursorIndex != -1)
      {
        TRect Rect = ItemRect(CursorIndex);
        DrawItem(CursorIndex, Rect, GetItemState(CursorIndex));
        }
    
      // Wenn vor dem Aufruf ein anderes Item hervorgehoben war, dieses
      // ermitteln und neu ohne Vorhebung zeichnen
      if ((iLastIndex != CursorIndex) && (iLastIndex > -1))
      {
        TRect Rect = ItemRect(iLastIndex);
        int Buffer = iLastIndex;
        iLastIndex = CursorIndex;
        DrawItem(Buffer, Rect, GetItemState(Buffer));
        }
      iLastIndex = CursorIndex; // neuen Index übernehmen
      }
    //---------------------------------------------------------------------------
    

    Zeile eingefügt, funktioniert! Habe aber noch ein Problem. Wie bekomme ich den "CursorIndex" an die Form gemeldet ?
    Bin bei solchen Code überfragt. Kann man mir hier auch helfen ?
    Hintergrund ist folgender. Beim überfahren der ListBox ändert sich die Zeilenfarbe. Dies ist alles ok. Nun möchte ich aber beim überfahren der Zeilen auch dessen Inhalt auslesen, ohne einen Maus Click ausführen zu müssen. Wenn dieses nicht der richtige Weg ist, lasst mich es wissen.

    Gruß Siegfried 😉



  • Hallo

    Du machst eine Nur-Lesen Eigenschaft für iLastIndex. Dann kannst du diesen Wert beliebig oft abrufen, und als Index für Items->Strings benutzen.

    bis bald
    akari



  • Dispatch!



  • Hallo,
    nochmals vielen Dank für die Hilfe. Habe eine Möglichkeit gefunden, meine Wünsche zu verwirklichen. Ich gehe davon aus, wenn ihr meine Lösung lest, das ihr die Hände über dem Kopf .....

    void __fastcall TListBoxEx::wmMouseMove(TMessage& Msg)
    {
    //
    //
      TPoint CursorPoint; // aktueller Punkt des Mauscursors
      GetCursorPos(&CursorPoint); // Cursor ermitteln
      CursorPoint = ScreenToClient(CursorPoint); // Cursor auf dieses Control umrechnen
      int CursorIndex = ItemAtPos(CursorPoint, true); // Item unter Cursor ermitteln
    
      // Wenn Item unter Cursor vorhanden, dieses neu zeichnen
      if (CursorIndex != -1)
      {
    //************************************************************
    // OnMouseMove Ereignis auswerten
    if (OnMouseMove) OnMouseMove(this, TShiftState(), 0, CursorIndex);
    //************************************************************
        TRect Rect = ItemRect(CursorIndex);
        DrawItem(CursorIndex, Rect, GetItemState(CursorIndex));
        }
    
      // Wenn vor dem Aufruf ein anderes Item hervorgehoben war, dieses
      // ermitteln und neu ohne Vorhebung zeichnen
      if ((iLastIndex != CursorIndex) && (iLastIndex > -1))
      {
        TRect Rect = ItemRect(iLastIndex);
        int Buffer = iLastIndex;
        iLastIndex = CursorIndex;
        DrawItem(Buffer, Rect, GetItemState(Buffer));
        }
      iLastIndex = CursorIndex; // neuen Index übernehmen
      }
    //---------------------------------------------------------------------------
    

    Wenn auch meine Möglichkeit getrickst ist, hat es mir den Erfolg gebracht.
    Über "Dispatch" können wir uns später unterhalten. Ich arbeite mit C++ seit etwa 6 Monate, komme aus der untersten Ebene über VB6 zu C++. Also muß ich sehr gut zuhören, was man mir vorschlägt. Es kann nur besser werden.
    bis bald
    Siegfried 👍 👍 👍


Anmelden zum Antworten