| Autor |
Beitrag |
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Do 26.06.08 11:42
Hallo
Für die farbige Textausgabe aus Listboxen etc. steht ja die Möglichkeit ListBox1DrawItem() zur Verfügung um einzelne Zeilen unterschiedlich einzufärben. Die Variante, ein einzelnes Wort aus einem String zu beeinflussen, ist damit aber nicht möglich.
Das wollte ich aber realisieren, habe aber nichts einschlägiges gefunden. Also habe ich ListBox1DrawItem() etwas abgeändert. Statt den gesamten String auszugeben, löse ich ihn in einzelne Worte auf und gebe die nacheinander aus. Durch voranstellen eines Steuerzeichens kann das einzelne Wort jetzt fast beliebig formatiert werden. Gewählt habe ich § für Farbe und Fett, das # für Farbe, Fett und kursiv. Die Auswahl der Steuerzeichen ist etwas eingeschränkt, man will sie ja vielleicht auch im normalen Text verwenden können.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| Procedure TForm10.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); Var ASt, tAst: String; m, l: Integer; begin tAst := ''; m := 1; With TListBox(Control) do begin Canvas.Font.Name := 'Arial'; Canvas.Font.Size := 10; Canvas.ItemHeight := 18; ASt := Items[Index]; Repeat If Ast <> '' then repeat tAst := tAst + Ast[m]; inc(m); until (Ast[m] = ' ') or (m >= length(Ast)+1); If (Pos('§',tAst) >= 1) or (Pos('#',tAst) >= 1) then begin If (Pos('§',tAst) >= 1) then begin Canvas.Font.Color:=clBlue; Canvas.Font.Style:=[fsbold]; Delete(tAst,Pos('§',tAst),1); end; If (Pos('#',tAst) >= 1) then begin Canvas.Font.Color:=clRed; Canvas.Font.Style:=[fsItalic] + [fsBold]; Delete(tAst,Pos('#',tAst),1); end; end else begin Canvas.Font.Style:=[]; Canvas.Font.Color:=clHotLight; end; Canvas.TextOut(Rect.Left+4, Rect.Top, tAst); l := Canvas.TextWidth(tAst); Rect.Left := Rect.Left + l; If tAst = '' then Exit; tAst := ''; until m >= length(Ast); end; end; |
Ein Beispiel habe ich mal angehängt. Vielleicht kann's ja jemand gebrauchen. Feedback ist willkommen.
Gruß Delphi10
Edit: Groben Fehler (With TListBox(Control) do....) korrigiert. 16.02.2009
Moderiert von Christian S.: Topic aus Algorithmen, Optimierung und Assembler verschoben am Do 26.06.2008 um 12:42
Moderiert von Christian S.: Topic aus VCL (Visual Component Library) verschoben am Do 26.06.2008 um 12:43
Moderiert von Narses: Topic aus der Library zurück nach VCL (Visual Component Library) verschoben am Mi 09.05.2012 um 23:40, da die Anforderungen für einen Library-Eintrag nicht erfüllt sind.
Einloggen, um Attachments anzusehen!
_________________ Salus populi suprema lex esto
Zuletzt bearbeitet von delphi10 am Mo 16.02.09 20:36, insgesamt 2-mal bearbeitet
|
|
delphi10 
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: So 29.06.08 16:40
Interessiert das hier wirklich niemand? Erstaunlich.
cu delphi10
_________________ Salus populi suprema lex esto
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: So 29.06.08 17:54
delphi10 hat folgendes geschrieben: | | Interessiert das hier wirklich niemand? Erstaunlich. |
Hi! Klar gibt es Interessenten. Das ganze gefällt mir recht gut, hab allerdings noch eine paar kleine Verbesserungsvorschläge.
Denn markiere ich Items einer Listbox mit angepassten OnDrawItem tauchen plötzlich schwarze Linien unter diesen auf. (s.A.)
Ein Canvas.FillRect(Rect); am Anfang der Procedure eliminiert diese aber.
Zudem wird der letzte Buchstabe eines formatierten Wortes nur fragmentiert angezeigt. (s.A.)
l := Canvas.TextWidth(tAst)+1; schafft da aber Abhilfe.
Desweiteren beginnt ein String bei mir bei eins und daher verstehe ich nicht ganz, weshalb Du hier (m >= length(Ast)+1) über die Länge des Strings hinausgehst.
Letztendlich wäre nun zu erwähnen, dass der Listbox-Style auf lbOwnerDrawVariable zustehen hat, damit es funktioniert.
Ansonsten vielen Dank!
Grüße,
Marc.
Einloggen, um Attachments anzusehen!
|
|
delphi10 
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Mo 30.06.08 10:30
| Zitat: | Letztendlich wäre nun zu erwähnen, dass der Listbox-Style auf lbOwnerDrawVariable zustehen hat, damit es funktioniert.
|
Hmmm, es gibt viele Wege nach Rom....
Innerhalb einer INIT-Procedur wird die ListBox auf
Delphi-Quelltext 1:
| Form10.ListBox1.Style := lbOwnerDrawVariable; |
gesetzt. Im Ereignis der ListBox OnDrawItem wird jetzt die Procedure
Delphi-Quelltext 1:
| Procedure TForm10.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); |
eingesetzt. Und schon läufts - jedenfalls bei mir (Delphi10). Das werd ich aber noch mal genau verifizieren und dann berichten.
Ja, mit den Spaces am Anfang und Ende eines markierten Wortes mußte ich auch ein wenig experimentieren.
cu delphi
Moderiert von Narses: Link entfernt
_________________ Salus populi suprema lex esto
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 15.12.08 19:32
Moin!
Ich habe noch einige Anmerkungen zu deinem Code-Vorschlag: - Du hast
Marc.s Vorschläge und Anmerkungen bisher nur kommentiert, aber offenbar nicht in den ersten Beitrag/Code einfließen lassen, oder? (siehe Anhang)
- Wenn man die Eigenschaften der Listbox nicht korrekt einstellt, funktioniert der Code nicht, da er ja nie aufgerufen wird. Du solltest diese erhebliche "Stolperfalle" besser deutlich im ersten Beitrag hervorheben!
- Du verwendest hier With TListBox(Control) do den übergebenen Parameter, um auf die entsprechende Listbox zuzugreifen, warum dann aber ein paar Zeilen später Form10.Listbox1.Font.Name := 'Arial'; Direktreferenzen? So kann man die Methode ja nur für eine spezielle Listbox verwenden...
- Wo wir gerade dabei sind: was ist, wenn ich den Font "Arial" nicht verwenden möchte? Oder eine andere Größe? Oder wenn der Benutzer zur Laufzeit selbst den Zeichensatz aussuchen können soll?
- Es wäre schön, wenn man die verwendeten Steuerzeichen einstellen könnte, um diese Zeichen auch verwenden zu können; Alternativ wäre auch Escaping ein Ansatz
- Du zerlegst in jedem OnDraw-Aufruf den darzustellenden String. Das ist ein potentieller Performance-Killer, noch dazu verwendest du String-by-Char-Concatenation, was ein Speicher-Killer ist. Deutlich optimaler wäre es, eine eigene Komponente von der Basisklasse abzuleiten und dieser ein internes String-Array/Liste zuzuordnen, das die zerlegten Elemente vorhält, damit das nicht jedes mal beim Zeichnen wieder gemacht werden muss. In der aktuellen Form ist dein Ansatz nur für wenige Einträge geeignet
cu
Narses
Einloggen, um Attachments anzusehen!
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: So 08.02.09 12:26
Hallo!
Könntest Du etwas zu Narses' Anregungen sagen oder sie umsetzen? Danke!
Grüße
Christian
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
delphi10 
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Mo 16.02.09 21:03
Narses hat folgendes geschrieben : | | Ich habe noch einige Anmerkungen zu deinem Code-Vorschlag: |
Hallo Narses
Ich habe diese Methode so verstanden, dass, sollte sie jemand in sein Projekt einbauen wollen, er sie sowieso anfassen muss. Deinen Ansprüchen - wie z.Bsp. ändern des Fonts während der Laufzeit kann und sollte sie nicht genügen. Das würde ich eher im Rahmen eines Projektes akzeptieren - Ich wollte diese Methode als Idee, als Denkvorlage verstanden wissen, nicht als blind übernehmbaren Quellcode.
Zweifellos richtig ist, dass es trotzdem fehlerfrei (im Sinne von: Stürzt nicht gleich ab) sein sollte. Den ListBox-Fehler habe ich oben korrigiert, war ein Überbleibsel aus einem Test. Da hätte ich noch 27mal drüberlesen können....
Dein Vorschlag mit dem String-Array ist genial, das werde ich auf jeden Fall noch nachreichen. Brauchs ja selber *g*
Soweit erstmal
Gruß Delphi10
_________________ Salus populi suprema lex esto
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: So 01.03.09 13:18
Schön wäre es, wenn Du noch im Beitrag verewigst, welche Einstellungen man bei der Listbox machen muss, damit die Methode richtig arbeitet. Also im Prinzip das, was Du hier beschrieben hast, nur irgendwie in den ersten Beitrag eingearbeitet.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
|