ListBox mit verschiedenen Farben selektiert

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

ListBox mit verschiedenen Farben selektiert

Beitrag von Mathias »

Wen ich in der ListBox mit der Maus einen Eintrag Selektiere, ist er Hellblau. Dasselbe wen ich mit der Tastatur Up und Down drücke.
Wechsle ich den Eintrag aber über ItemIndex, ist er in einem dünklerem Blau. Siehe Anhang.
Sobald wieder eine Maus oder Tastatur Aktion kommt, wird es wieder heller.

Wieso ist dies so ?
Kann man dies verhindern ?

Was mir bekannt ist, wen man Multiselected aktiviert hat, ist dies normal.

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.Add('aaa');
  ListBox1.Items.Add('bbb');
  ListBox1.Items.Add('ccc');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.ItemIndex:=2;
end;
Dateianhänge
Bildschirmfoto vom 2024-06-16 17-25-11.png
Bildschirmfoto vom 2024-06-16 17-25-11.png (4.64 KiB) 1047 mal betrachtet
Bildschirmfoto vom 2024-06-16 17-25-03.png
Bildschirmfoto vom 2024-06-16 17-25-03.png (4.61 KiB) 1047 mal betrachtet
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Soner
Beiträge: 734
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von Soner »

Meine Vermutung ist Focus, durch Maus und Tastatur hat Listbox Focus, aber mit mit ItemIndex nicht unbedigt.
Versuch mal mit:

Code: Alles auswählen

if ListBox1.CanFocus then ListBox1.Focused:=true;
ListBox1.ItemIndex:=1;

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von theo »

Es gibt viele Status für eine Listbox-Zeile, siehe LCLType

Code: Alles auswählen

  TOwnerDrawStateType = (
    odSelected, odGrayed, odDisabled, odChecked,
    odFocused, odDefault, odHotLight, odInactive, odNoAccel,
    odNoFocusRect, odReserved1, odReserved2, odComboBoxEdit,
    odBackgroundPainted  // item background already painted
    );    

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von Mathias »

Soner hat geschrieben: Mo 17. Jun 2024, 13:49 Meine Vermutung ist Focus, durch Maus und Tastatur hat Listbox Focus, aber mit mit ItemIndex nicht unbedigt.
Versuch mal mit:

Code: Alles auswählen

if ListBox1.CanFocus then ListBox1.Focused:=true;
ListBox1.ItemIndex:=1;
Dies kann nicht gehen, Fucused ist eine Funktion und kein Property.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von Mathias »

Es gibt viele Status für eine Listbox-Zeile, siehe LCLType
Wie komme ich an die einzelnen Zeilen ran ?
Mir sind nur die Items bekannt, welche auf die StringList zeigt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von theo »

Mathias hat geschrieben: Mo 17. Jun 2024, 17:47
Es gibt viele Status für eine Listbox-Zeile, siehe LCLType
Wie komme ich an die einzelnen Zeilen ran ?
Mir sind nur die Items bekannt, welche auf die StringList zeigt.
OnDrawItem mit entsprechendem "Style" "lbOwnerDrawxxx"

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von Mathias »

OnDrawItem mit entsprechendem "Style" "lbOwnerDrawxxx"
Mit anderen Worten, man muss sich selbst um das Befüllen der List-Canvas kümmern.

Ich habe es jetzt so probiert und bis auf die TextPosition, welche ein paar Pxel daneben ist, würde es gehen.
Wen ich die ganzen Canvas-Ausgaben weglasse, dann zeichnet er die blauen Balken wie vorher, einfach ohne Text.
Ist das der Sinn der Sache ?
Irgendwie krass, so viele Zeilen für das komische Problem.

Code: Alles auswählen

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: integer; ARect: TRect; State: TOwnerDrawState);
begin
  ListBox1.Canvas.Pen.Color := ListBox1.Canvas.Brush.Color;
  ListBox1.Canvas.Rectangle(ARect);

  if odSelected in State then  begin
    ListBox1.Canvas.Font.Color := clRed;
  end else begin
    ListBox1.Canvas.Font.Color := clGreen;
  end;
  ListBox1.Canvas.TextOut(ARect.Left, ARect.Top, ListBox1.Items[Index]);
end;  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von theo »

Mathias hat geschrieben: Mo 17. Jun 2024, 17:42
Soner hat geschrieben: Mo 17. Jun 2024, 13:49 Meine Vermutung ist Focus, durch Maus und Tastatur hat Listbox Focus, aber mit mit ItemIndex nicht unbedigt.
Versuch mal mit:

Code: Alles auswählen

if ListBox1.CanFocus then ListBox1.Focused:=true;
ListBox1.ItemIndex:=1;
Dies kann nicht gehen, Fucused ist eine Funktion und kein Property.
Dann halt ListBox1.SetFocus;

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von Mathias »

Dann halt ListBox1.SetFocus;
Mit dem geht es, mit einem kleinen Schönheitsfehler. Der alte Balken wird rasch Dunkelblau, bevor es umschaltet.

Code: Alles auswählen

    ListBox1.ItemIndex := index + 1;
    ListBox1.SetFocus;
Jetzt sehe ich auch der Sinn an der Sache. Hellblau ist, wen es Fokusiert ist. Und Dunkelblau, wen er aktiv ist, aber keinen Fokus hat.
Mir ist dies erst jetzt im direkten Vergleich aufgefallen, das es fast gleiche Blau sind.

Ich werde es auf Standard belassen. Da der Fokus auf dem Button liegt, welcher den Balken bewegte.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6955
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von Mathias »

Ich habe doch noch eine Frage dazu.
Wen man eine ListBox per Default-Style lässt, wird der Text in der Höhe der einzelnen Felder schön brav zentriert.

Wie kann ich das mit der eigenen Variante auch machen ?
Klar ich könnte bei TextOut ein Offset mitgeben. Aber dies würde doch bei einer anderen Schrift nicht mehr stimmen.

Code: Alles auswählen

procedure TForm1.ListBoxDrawItem(Control: TWinControl; Index: integer; ARect: TRect; State: TOwnerDrawState);
begin
  ListBox.Canvas.Pen.Color := ListBox.Canvas.Brush.Color;
  ListBox.Canvas.Rectangle(ARect);

  if odSelected in State then  begin
    ListBox.Canvas.Font.Color := clRed;
  end else begin
    ListBox.Canvas.Font.Color := clGreen;
  end;
  ListBox.Canvas.Rectangle(ARect);
  ListBox.Canvas.TextOut(ARect.Left, ARect.Top, ListBox.Items[Index]);
end; 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10920
Registriert: Mo 11. Sep 2006, 19:01

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von theo »

Warum nimmst du dafür nicht TCanvas.TextRect mit dem TTextStyle?

wp_xyz
Beiträge: 5188
Registriert: Fr 8. Apr 2011, 09:01

Re: ListBox mit verschiedenen Farben selektiert

Beitrag von wp_xyz »

Wie wär's mit ein bisschen Mathematik? Canvas.TextOut beginnt den Text an seiner linken/oberen Ecke --> Berechne die vertikale Mitte der Zeile und gehe um die halbe Texthöhe nach oben:

Code: Alles auswählen

var
  h, x, y: Integer;
...
  h := Listbox.Canvas.TextHeight('Tg');
  x := ARect.Left + 2;
  y := (ARect.Top + ARect.Bottom - h) div 2;
  Listbox.Canvas.TextOut(x, y, Listbox.Items[Index]);

Antworten