Delphi-Forum.de Delphi-Library.de
C-Sharp-Forum.de C-Sharp-Library.de
Registrieren Login Suche Hilfe Sitemap
Farbige Textausgabe für Listbox u.ä.
spacer
Autor Nachricht
delphi10
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic starofftopic star

Beiträge: 394
Dabei seit: 10.09.2007
Wohnort: Salzgitter

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: Do 26.06.08 12:42  Antworten mit Zitat Beitrag melden
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.
ausblenden volle Höhe Delphi-Quelltext markieren
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, //Ausgabestring
tAst: String; //Teilausgabestring (einzelnes Wort)
m, //Zähler durch den Ausgabestring
l: Integer; //Länge des Teilstrings im Canvas
begin
tAst := '';
m := 1;
With TListBox(Control) do
begin
Canvas.Font.Name := 'Arial';
Canvas.Font.Size := 10;
Canvas.ItemHeight := 18;
ASt := Items[Index];
Repeat
// ++++++++++++++++++++++++++++++++++++++++++++++++++
// Löst den Ausgabestring in einzelne Worte auf. Delimiter ist space
If Ast <> '' then
repeat
tAst := tAst + Ast[m];
inc(m);
until (Ast[m] = ' ') or (m >= length(Ast)+1);
// ++++++++++++++++++++++++++++++++++++++++++++++++++
// Entsprechend des Steuerzeichens das einzelne Wort behandeln
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); //Teilstring in das Canvas schreiben
l := Canvas.TextWidth(tAst); //Länge des Teilstrings bzw. Platzbedarf im Canvas ermitteln
Rect.Left := Rect.Left + l; //Zum linken X-Wert der Canvas addieren (für den nächsten Teilstring)
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 user profile iconChristian S.: Topic aus Algorithmen, Optimierung und Assembler verschoben am Do 26.06.2008 um 12:42
Moderiert von user profile iconChristian S.: Topic aus VCL (Visual Component Library) verschoben am Do 26.06.2008 um 12:43
Einloggen, um Attachments anzusehen!
_________________
Salus populi suprema lex esto


Zuletzt bearbeitet von delphi10 am Mo 16.02.09 21:36, insgesamt 2-mal bearbeitet
Private Nachricht sendenPosting in privater Nachricht zitieren
delphi10
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic starofftopic star

(Threadstarter)

Beiträge: 394
Dabei seit: 10.09.2007
Wohnort: Salzgitter

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: So 29.06.08 17:40  Antworten mit Zitat Beitrag melden
Interessiert das hier wirklich niemand? Erstaunlich.
cu delphi10

_________________
Salus populi suprema lex esto
Private Nachricht sendenPosting in privater Nachricht zitieren
Marc.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star

Beiträge: 1571
Erhaltene Danke: 4
Dabei seit: 09.11.2005


Win 7, VM
BeitragVerfasst: So 29.06.08 18:54  Antworten mit Zitat Beitrag melden
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!
_________________
Nothing Is Real
Private Nachricht sendenPosting in privater Nachricht zitieren
delphi10
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic starofftopic star

(Threadstarter)

Beiträge: 394
Dabei seit: 10.09.2007
Wohnort: Salzgitter

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: Mo 30.06.08 11:30  Antworten mit Zitat Beitrag melden
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
ausblenden Delphi-Quelltext markieren
1:
Form10.ListBox1.Style := lbOwnerDrawVariable;

gesetzt. Im Ereignis der ListBox OnDrawItem wird jetzt die Procedure
ausblenden Delphi-Quelltext markieren
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 user profile iconNarses: Link entfernt

_________________
Salus populi suprema lex esto
Private Nachricht sendenPosting in privater Nachricht zitieren
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic star
Moderator

Beiträge: 7363
Erhaltene Danke: 10
Dabei seit: 25.07.2004
Wohnort: Gelsenkirchen

W2k, WXPpro
D6pe, D7pro
BeitragVerfasst: Mo 15.12.08 20:32  Antworten mit Zitat Beitrag melden
Moin!

Ich habe noch einige Anmerkungen zu deinem Code-Vorschlag:
  • Du hast user profile iconMarc.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.
Private Nachricht sendenPosting in privater Nachricht zitieren
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic star
Chefentwickler

Beiträge: 17543
Erhaltene Danke: 105
Dabei seit: 07.07.2002
Wohnort: Server-Souterrain

Win 7
Delphi Prism, C# (VS 2010)
BeitragVerfasst: So 08.02.09 13:26  Antworten mit Zitat Beitrag melden
Hallo!

Könntest Du etwas zu Narses' Anregungen sagen oder sie umsetzen? Danke! :-)

Grüße
Christian

_________________
I am of peace. Always.
Vom 9.9. bis 13.9. in Urlaub
Private Nachricht sendenPosting in privater Nachricht zitieren Webseite dieses Mitglieds besuchen
delphi10
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic starofftopic star

(Threadstarter)

Beiträge: 394
Dabei seit: 10.09.2007
Wohnort: Salzgitter

W2K, XP, Vista64, Win7 64
RAD-Studio 2010
BeitragVerfasst: Mo 16.02.09 22:03  Antworten mit Zitat Beitrag melden
user profile iconNarses hat folgendes geschrieben icon mini page:
Moin!

Ich habe noch einige Anmerkungen zu deinem Code-Vorschlag:
  • Du hast user profile iconMarc.s Vorschläge und Anmerkungen bisher nur kommentiert, aber offenbar nicht in den ersten Beitrag/Code einfließen lassen, oder? (siehe Anhang)
    [*1]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!
    [*2]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...
    [*3]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?
    [*4]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
    [*5]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


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
Private Nachricht sendenPosting in privater Nachricht zitieren
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starhalf offtopic starofftopic star
Chefentwickler

Beiträge: 17543
Erhaltene Danke: 105
Dabei seit: 07.07.2002
Wohnort: Server-Souterrain

Win 7
Delphi Prism, C# (VS 2010)
BeitragVerfasst: So 01.03.09 14:18  Antworten mit Zitat Beitrag melden
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.

_________________
I am of peace. Always.
Vom 9.9. bis 13.9. in Urlaub
Private Nachricht sendenPosting in privater Nachricht zitieren Webseite dieses Mitglieds besuchen
Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.


Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.
Beiträge vom vorherigen Thema anzeigen:   
home home