Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi ListBox (https://www.delphipraxis.net/180667-listbox.html)

value is NULL 6. Jun 2014 09:46

ListBox
 
Hi ihr lieben

Ich weiß das Thema gibt es schon zur genüge aber irgendwie komme ich nicht auf das richtige Ergebnis.
Ich habe eine ListBox in der ich verschiedene Items eintragen lassen vom User. Sprich er hat ein Edit und einen Button.
Bei einem klick auf den button wird der Eintrag des Edit Feldes in die Listbox übernommen.

Ist die Liste befüllt so durchlaufe ich die liste und sehen ach, ob es die Einträge in einer Datenbank gibt. Sollte es einen Eintrag nicht geben so möchte ich von diesem Item die Hintergrundfarbe auf zB Gelb ändern.

hat jemand einen Schnippsel für mich mit dem ich ein bestimmtes Item einfärben kann?

Danke im Voraus!

bernau 6. Jun 2014 09:57

AW: ListBox
 
Versuche es mal mit "OnDrawItem".

baumina 6. Jun 2014 10:02

AW: ListBox
 
http://delphi.about.com/cs/adptips20...ltip0602_4.htm

value is NULL 6. Jun 2014 10:06

AW: ListBox
 
Ja das hab ich schon gesehen, aber: Das funktioniert ja nur wenn ich die Items auch zur Listbox hinzufüge. Wie ändere ich bereits bestehende Einträge?

baumina 6. Jun 2014 10:13

AW: ListBox
 
Zitat:

Zitat von value is NULL (Beitrag 1261548)
... Das funktioniert ja nur wenn ich die Items auch zur Listbox hinzufüge...

Wie kommst Du denn darauf? OnDrawItem hat nichts mit dazufügen zu tun, das ist einzig und alleine das Event, das ausgelöst wird, wenn ein Item auf dem Bildschirm angezeigt wird.

mkinzler 6. Jun 2014 10:16

AW: ListBox
 
Genauso

value is NULL 6. Jun 2014 10:19

AW: ListBox
 
Hä? xD ... Sorry vermutlich ne Blockade gerade:

Für mich klang das so, als würde dieses Event nur aufgerufen, wenn ich ein neues Item hinzufüge zB Listbox1.Items.Add('WasAuchImmer');
Aber die Werte sind ja bereits in der Liste die ich dann mit folgender Schleife durchlaufe:

Delphi-Quellcode:
while i < Form1.ListBox1.Count do begin
    userId := sqlst.query('select id from user_ where username = '''+Form1.listbox1.Items[i]+'''');
    //user not found
    if userId = '' then //Change Color of current line - cLYellow
    i := i + 1;
end;
Sorry das ich mich gerade so "blöd" anstelle ^^... rufe ich das Event dann erneut auf? Sprich manuell? oder wie ...

Neutral General 6. Jun 2014 10:23

AW: ListBox
 
Erspar dir doch ein paar Fragen indem du dir das Event mal anschaust und rumprobierst..
Dann erübrigt sich dein letzter Post.

mkinzler 6. Jun 2014 10:23

AW: ListBox
 
Bei jedem Zeichnen eines Eintrags (wird pro Eintrag aufgerufen).
Erzwinge ein Neuzeichnen der ListBox

value is NULL 6. Jun 2014 10:37

AW: ListBox
 
Ich checks nicht :/

DeddyH 6. Jun 2014 10:41

AW: ListBox
 
Wenn ein Eintrag gezeichnet werden muss (z.B. weil gescrollt wurde), wird das OnDrawItem (wieso heißt das wohl so?) ausgeführt.

baumina 6. Jun 2014 10:45

AW: ListBox
 
Nehmen wir mal den Code zur Hand und ändern den ein wenig :

Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem
    (Control: TWinControl; Index: Integer;
    Rect: TRect; State: TOwnerDrawState) ;
 var
    myColor: TColor;
    myBrush: TBrush;
 begin
    myBrush := TBrush.Create;
    with (Control as TListBox).Canvas do
    begin
(* das machen wir raus
      if not Odd(Index) then
        myColor := clSilver
      else
        myColor := clYellow;
*)
      // und das machen wir stattdessen rein
      If InDB(Index) then // die Funktion InDB musst dann noch schreiben, diese schaut in der DB nach und gibt True zurück wenn der Item in der DB gefunden wurde
        myColor := clYellow
      else
        myColor := clWhite;
       
      myBrush.Style := bsSolid;
      myBrush.Color := myColor;
      Windows.FillRect(handle, Rect, myBrush.Handle) ;
      Brush.Style := bsClear;
      TextOut(Rect.Left, Rect.Top,
              (Control as TListBox).Items[Index]) ;
      MyBrush.Free;
    end;
 end;

value is NULL 6. Jun 2014 10:51

AW: ListBox
 
Das heisst ich müsste eigentlich meinen Programm Aufbau ändern. Aktuell lasse ich die Liste zuerst anlegen und prüfe dann erst
die Datenbank. So müsste ich praktisch bei jedem "Add Item" gleich prüfen habe ich das jetzt richtig verstanden?

DeddyH 6. Jun 2014 10:57

AW: ListBox
 
IMO müsste es genügen, ein Neuzeichnen der ListBox zu erzwingen.

value is NULL 6. Jun 2014 11:00

AW: ListBox
 
@baumina
Mit dieser Funktion müsste ich den Programmaufbau komplett ändern, das wäre zuviel Aufwand :/

@DeddyH
Da ich leider kein UI Spezi bin: Wie würde ich eine Listbox neu zeichnen?

baumina 6. Jun 2014 11:06

AW: ListBox
 
ich gebs auf ...

DeddyH 6. Jun 2014 11:07

AW: ListBox
 
Wenn ListBox.Repaint nichts bringt, kann man es unsauber versuchen, indem man Visible auf false und wieder auf true setzt. Das ist aber sehr Quick & Dirty.

value is NULL 6. Jun 2014 11:14

AW: ListBox
 
@baumina

Sorry ich verstehs echt nicht... Aber wenn ich mir deinen Code ansehe:

Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem
    (Control: TWinControl; Index: Integer;
    Rect: TRect; State: TOwnerDrawState) ;
 var
    myColor: TColor;
    myBrush: TBrush;
 begin
    myBrush := TBrush.Create;
    with (Control as TListBox).Canvas do
    begin
(* das machen wir raus
      if not Odd(Index) then
        myColor := clSilver
      else
        myColor := clYellow;
*)
      // und das machen wir stattdessen rein
      If InDB(Index) then // die Funktion InDB musst dann noch schreiben, diese schaut in der DB nach und gibt True zurück wenn der Item in der DB gefunden wurde
        myColor := clYellow
      else
        myColor := clWhite;
       
      myBrush.Style := bsSolid;
      myBrush.Color := myColor;
      Windows.FillRect(handle, Rect, myBrush.Handle) ;
      Brush.Style := bsClear;
      TextOut(Rect.Left, Rect.Top,
              (Control as TListBox).Items[Index]) ;
      MyBrush.Free;
    end;
 end;
Dann müsste ich mir eine Funktion schreiben die zb Folgendes tut: (ganz grob)
- Datenbank connect
- überprüfen ob user vorhanden (true od. false returnen)
- Disconnect

Das Problem ist aber, das der User zuerst die Liste anlegen muss. Dann gibt es eine Art "Execute" Button und in dieser Prozedur werden dann etliche Datenbankspezifische Dinge
durchgeführt (abfragen, updates, inserts etc.). Wenn es hier ein Problem gibt zB. User nicht vorhanden, Färbe das Item yellow, bei SQL Update Fehler red und bei success green.

Dh. ich bräuchte die Möglichkeit in meiner "SQL-Funktion", sprich wenn ich die Liste abarbeite das Item[x] nachträglich zu ändern.

Sorry falls ich mich blöd stelle. Habe mich vorhin mit OnDrawItem gespielt und der einzige Erfolg war, das ich beim !Hinzufügen! die Farbe ändern kann, jedoch nicht bei einem bestehenden. oder wie gesagt ich bin zu blöd ^^

LG

DeddyH 6. Jun 2014 11:17

AW: ListBox
 
http://docwiki.embarcadero.com/Libra...Box.OnDrawItem
Zitat:

Mit einer Ereignisbehandlungsroutine für OnDrawItem können Sie die Einträge von Listenfeldern zeichnen, deren Eigenschaft Style den Wert lbOwnerDrawFixed, lbOwnerDrawVariable oder lbVirtualOwnerDraw hat. OnDrawItem tritt immer dann ein, wenn ein Eintrag im Listenfeld angezeigt werden muss. Dieses Ereignis gibt es nur bei Owner-Draw-Listenfeldern.

baumina 6. Jun 2014 11:39

AW: ListBox
 
OK, Vorschlag. Führe beim Füllen deiner ListBox eine Liste mit Farben, oder schreibe die Farben in die Objects der der ListboxItems. Am Anfang alle clWhite. Beim Execute-Knopf änderst du dann die Farben anhand des Items auf Rot/Grün/Gelb. Im OnItemDraw nimmst du dann die Farbe aus der Liste oder aus den Objects, wie immer du dich entschieden hast diese mitzuführen.

value is NULL 6. Jun 2014 11:40

AW: ListBox
 
Ich komm nicht dahinter... Aber trotzdem danke für die Hilfe

himitsu 6. Jun 2014 11:54

AW: ListBox
 
Hat eigentlich schon jemand erwähnt, daß der Threadtitel absolut nichts zum Problem aussagt?

Und ja, es gibt schon massig Themen, wo irgendwer irgendwelche Probleme mit seiner ListBox hat.

Jumpy 6. Jun 2014 12:00

AW: ListBox
 
Nur sinngemäß, da ich gerade kein Delphi offen habe, geht bestimmt auch einfacher:

Delphi-Quellcode:
type
  TLBColor=class
    public
     Color:TColor;
  end;


//Item zur Liste hinzufügen:
procedure TForm1.Button1Click(Sender: TObject);
var t:TLBColor;
begin
  t:=TLBColor.Create;
  t.Color:=clWhite;
  Listbox1.AddItem('foo',t);
end;

//in deiner Prüffunktion
while i < Form1.ListBox1.Count do begin
    userId := sqlst.query('select id from user_ where username = '''+Form1.listbox1.Items[i]+'''');
    //user not found
    if userId = '' then //Change Color of current line - cLYellow
      TLBColor(Listbox1.Items.Objects(i)).Color:=clRed;
    i := i + 1;
end;



procedure TForm1.ListBox1DrawItem
    (Control: TWinControl; Index: Integer;
    Rect: TRect; State: TOwnerDrawState) ;
 var
    myColor: TColor;
    myBrush: TBrush;
 begin
    myBrush := TBrush.Create;
    with (Control as TListBox).Canvas do
    begin
      myColor := TLBColor(Listbox1.Items.Objects(index)).Color;
      myBrush.Style := bsSolid;
      myBrush.Color := myColor;
      Windows.FillRect(handle, Rect, myBrush.Handle) ;
      Brush.Style := bsClear;
      TextOut(Rect.Left, Rect.Top,
              (Control as TListBox).Items[Index]) ;
      MyBrush.Free;
    end;
 end;

value is NULL 6. Jun 2014 12:21

AW: ListBox
 
Jetzt hab ichs kapiert.... funktioniert!

Danke an alle für die Geduld!

Popov 6. Jun 2014 14:13

AW: ListBox
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von value is NULL (Beitrag 1261557)
Für mich klang das so, als würde dieses Event nur aufgerufen, wenn ich ein neues Item hinzufüge zB Listbox1.Items.Add('WasAuchImmer');

Bei OnDrawIten wird jedes Mal gezeichnet wenn es nötig ist. OnMeasureItem wird nur ein mal ausgeführt, z. B. bei deinem Add.

Zum Code. Den muss man nicht so komplex machen wie hier:
Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem
    (Control: TWinControl; Index: Integer;
    Rect: TRect; State: TOwnerDrawState) ;
 var
    myColor: TColor;
    myBrush: TBrush;
 begin
    myBrush := TBrush.Create;
    with (Control as TListBox).Canvas do
    begin
      myColor := TLBColor(Listbox1.Items.Objects(index)).Color;
      myBrush.Style := bsSolid;
      myBrush.Color := myColor;
      Windows.FillRect(handle, Rect, myBrush.Handle) ;
      Brush.Style := bsClear;
      TextOut(Rect.Left, Rect.Top,
              (Control as TListBox).Items[Index]) ;
      MyBrush.Free;
    end;
 end;
Im Grunde reicht es, was Farbe angeht, das:
Delphi-Quellcode:
 begin
    with (Control as TListBox).Canvas do
    begin
      ...
      Brush.Color := myColor;
      ...
    end;
 end;
Zum empfehlen ist sich an die Listbox ein Objekt mit Infox anzuhängen. Kein großer Aufwand, aber bei OnDrawItem kann man sich die nötigen Infos bezüglich Farbe und weitere Formatierung da rausholen.

Im Anhang habe ich ein kleines Beispiel das zeigt wie das mit dem angehängtem Objekt funktioniert und wie man jeden Item individuell einfärben kann:

Sir Rufo 6. Jun 2014 19:26

AW: ListBox
 
Zitat:

Zitat von Popov (Beitrag 1261609)
Zitat:

Zitat von value is NULL (Beitrag 1261557)
Für mich klang das so, als würde dieses Event nur aufgerufen, wenn ich ein neues Item hinzufüge zB Listbox1.Items.Add('WasAuchImmer');

OnMeasureItem wird nur ein mal ausgeführt, z. B. bei deinem Add.

Bist du dir da sicher?

Popov 6. Jun 2014 19:57

AW: ListBox
 
Nach meiner Kenntnis, Beobachtungen und ausführlichen Tests ja. Wobei mit "einmal" nicht einmal pro ListBox, sondern einmal pro Item, und zwar bei Erstellung des jeweiligen Items gemeint ist.

Wie das in neueren Delphis ist, weiß ich nicht, bei Delphi 7 ist es so. Wenn du andere Kenntnis hast oder Möglichkeiten kennst, her damit.

Luckie 8. Jun 2014 06:01

AW: ListBox
 
Also eigentlich hätte ich jetzt erwartet, das OnMeasureItem bei jedem Zeichen aufgerufen wird, den die Listbox weiß ja vorher nicht, was sie wie Zeichnen soll.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:25 Uhr.

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