Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Einzelne Wörter in TListBox fett zeichnen (https://www.delphipraxis.net/174396-einzelne-woerter-tlistbox-fett-zeichnen.html)

Dennis07 20. Apr 2013 00:14

Einzelne Wörter in TListBox fett zeichnen
 
Hallo,
tut mir leid, wenn ich euch schon wieder zur Hilfe ziehen muss, aber leider gibt es wohl noch kein entsprechendes Thema oder eine passende Hilfe auf Google.

Also: Ich habe eine TListBox. Wie man ganze Einträge (also Zeilen) fett zeichnen kann, weiß ich ja.
Nur, wie kann ich mit DrawItem nur einzelte Wörter oder Buchstaben fett zeichnen?
Die Methode OnDrawItem kennt ja leider keinen Zeichenindex, sondern nur einen Zeilenindex.

Gibt es hier auch eine Möglichkeit, dieses evtl. zu bekommen?

MFG

Amateurprofi 20. Apr 2013 02:42

AW: Einzelne Wörter in TListBox fett zeichnen
 
Indem du den Text der gerade zu zeichnenden Zeile zerlegst und separat ausgibst.

Nehmen wir an, alle Ziffern sollen Fett geschrieben werden.

In etwa würde ich mir das dann (ganz primitiv) so vorstellen:
Delphi-Quellcode:
var i:integer; s:string;
begin
   with TListBox(Sender), Canvas, Font do begin
      PenPos:=Rect.TopLeft;
      s:=Items[Index];
      for i:=1 to Length(s) do begin
         if s[i] in ['0'..'9'] then Style:=[fsBold] else Style:=[];
         TextOut(PenPos.X,PenPos.Y,s[i]);
      end;
   end;
end;

Dennis07 20. Apr 2013 10:16

AW: Einzelne Wörter in TListBox fett zeichnen
 
Danke bis hierhin schonmal.
Nun hätte ich noch drei andere Fragen. Und zwar:
  • Wann muss ich als TListBox.Style OwnerDrawFixed und wann OwnerDrawVariable einsetzen?
  • Wie kann ich verhindern, dass Fett gedruckter Text in manchen Windows-Designs so hässlich über den Rand der TListbox steht?
  • In meinem bisherigen Versuch werden Tabstopps beim Draw-Vorgang ignoriert und erscheinen am Ende nicht in der Listbox. Wie kann ich das beheben?

Ich hoffe, ihr könnt mir auch hier wieder kurz Hilfe leisten.
Danke.

Luckie 20. Apr 2013 20:31

AW: Einzelne Wörter in TListBox fett zeichnen
 
Bei der API Funktion Drawtext kannst du mit den Flags bestimmen, wie Tabs behandelt werden sollen.

Amateurprofi 20. Apr 2013 20:51

AW: Einzelne Wörter in TListBox fett zeichnen
 
Zitat:

Wann muss ich als TListBox.Style OwnerDrawFixed und wann OwnerDrawVariable einsetzen?
OwnerDrawFixed = immer gleiche Zeilenhöhe.
OwnerDrawVariable = Zeilenhöhe für jede Zeile separat bestimmen. Dann wird vor OnDrawItem ein OnMeasureItem ausgelöst, in dem du die Zeilenhöhe festlegen kannst.

Zitat:

Wie kann ich verhindern, dass Fett gedruckter Text in manchen Windows-Designs so hässlich über den Rand der TListbox steht?
Ist mir noch nie paasiert. Wenn du in den Canvas der ListBox zeichnest dann kann m.E. auch nur innerhalb der ListBox gezeichnet werden.

Vielleicht postest du mal deinen Code?

Dennis07 20. Apr 2013 22:13

AW: Einzelne Wörter in TListBox fett zeichnen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Amateurprofi (Beitrag 1212211)
OwnerDrawFixed = immer gleiche Zeilenhöhe.
OwnerDrawVariable = Zeilenhöhe für jede Zeile separat bestimmen. Dann wird vor OnDrawItem ein OnMeasureItem ausgelöst, in dem du die Zeilenhöhe festlegen kannst.

Okay. Und wie kann ich das genau machen, d.h. wie kann ich herausfinden, wie viel platz eine Zeile benötigt, um richtig dargestellt werden zu können?

Zitat:

Zitat von Amateurprofi (Beitrag 1212211)
Ist mir noch nie paasiert. Wenn du in den Canvas der ListBox zeichnest dann kann m.E. auch nur innerhalb der ListBox gezeichnet werden.

Nein, so meine ich das nicht. Was ich meine ist: Es wird über das Item der Listbox hinaus das Rect des fetten Texts gezeichnet, wenn dieser Eintrag makiert wurde (siehe Screenshot).


Zitat:

Zitat von Amateurprofi (Beitrag 1212211)
Vielleicht postest du mal deinen Code?

Ehm, da müsstest du mir sagen, welche Teile relevant für dich sind. Der Code ist zu lang, als dass ich es jemandem zumuten könnte, ich zu lesen. Außerdem werdende ich (ein bischen) Code von anderen, müsste also erst den Papierkram erledigen.

MFG und Danke bis hierhin;
Dennis

Amateurprofi 22. Apr 2013 02:23

AW: Einzelne Wörter in TListBox fett zeichnen
 
Zitat:

Zitat von Dennis07 (Beitrag 1212214)
Zitat:

Zitat von Amateurprofi (Beitrag 1212211)
OwnerDrawFixed = immer gleiche Zeilenhöhe.
OwnerDrawVariable = Zeilenhöhe für jede Zeile separat bestimmen. Dann wird vor OnDrawItem ein OnMeasureItem ausgelöst, in dem du die Zeilenhöhe festlegen kannst.

Okay. Und wie kann ich das genau machen, d.h. wie kann ich herausfinden, wie viel platz eine Zeile benötigt, um richtig dargestellt werden zu können?

Indem du die Höhe des auszugebenden Textes berechnest, mit Canvas.TextHeight zum Beispiel.


Zitat:

Zitat von Dennis07 (Beitrag 1212214)
Zitat:

Zitat von Amateurprofi (Beitrag 1212211)
Vielleicht postest du mal deinen Code?

Ehm, da müsstest du mir sagen, welche Teile relevant für dich sind. Der Code ist zu lang, als dass ich es jemandem zumuten könnte, ich zu lesen. Außerdem werdende ich (ein bischen) Code von anderen, müsste also erst den Papierkram erledigen.

Na ja, die ListBoxDrawItem Procedure, denke ich.
Wie soll man dir helfen, wenn man nicht weiß, wie du die Texte ausgibst.

jaenicke 22. Apr 2013 09:34

AW: Einzelne Wörter in TListBox fett zeichnen
 
Ich würde einfach TJvHTListBox aus der JVCL verwenden. Da kannst du einfach HTML zur Formatierung nutzen. Das ist sicher ein klein wenig langsamer, aber in einer Listbox hat man ja auch kaum tausende von Einträgen.

Dennis07 22. Apr 2013 12:16

AW: Einzelne Wörter in TListBox fett zeichnen
 
Hallo,
Ich habe noch keine OnDrawItem-Prozedur für DIESE ListBox, da ich es im Grunde nur für den Highlight des jeweiligen Texts zwischen dem Zeichen #9 und : brauche.
Das ist die erste ListBox. Die zweite, die man auch auf dem Screenshot meines letzten Beitrags sehen kann, hat folgenden Code:

Delphi-Quellcode:
  TfmChat = class(TForm)
  public
    { Public-Deklarationen }
    NickName: String;                               //Anzeigename
  end;

{ ... }

procedure TfmChat.lbPeopleDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
{ Eigenen Namen fett anzeigen }
begin
  if Index = lbPeople.Items.IndexOf(NickName) then
  begin
    (Control as TListBox).Canvas.Font.Style := [fsBold];
  end else
  begin
    (Control as TListBox).Canvas.Font.Style := [];
  end;
  with Control as TListBox do
  begin
    Canvas.Pen.Color := lbPeople.Color;
    Canvas.FillRect(Rect);
    Canvas.TextOut(Rect.Left + 2,Rect.Top - 1,Items[Index]);
  end;
end;

Amateurprofi 22. Apr 2013 13:37

AW: Einzelne Wörter in TListBox fett zeichnen
 
Zitat:

Wie kann ich verhindern, dass Fett gedruckter Text in manchen Windows-Designs so hässlich über den Rand der TListbox steht?
Ich vermute, du meinst, dass oberhalb des Textes 1 Pixel oberhalb der eigentlichen Zeile blau eingefärbt ist.
Das hast du mit
Delphi-Quellcode:
Canvas.TextOut(Rect.Left + 2,Rect.Top - 1,Items[Index]);
so vorgegeben.
Mit Rect.Top-1 positionierst du den Text 1 Pixel oberhalb der Zeile.
Abhilfe:
Delphi-Quellcode:
Canvas.TextRect(Rect,Rect.Left+2,Rect.Top-1,Items[Index]);
Das "FillRect" kannst du dir dann auch sparen.

Dennis07 22. Apr 2013 14:27

AW: Einzelne Wörter in TListBox fett zeichnen
 
Danke, das hat (zumindest für WinAero) schonmal geholfen.
Der Grund, weshalb ich den einen Pixel abziehen musste war, dass es sonst auf WinXP im Klassischen Design zu genau dem umgekehrten Fehler kam.

MFG

Dennis07 30. Apr 2013 16:10

AW: Einzelne Wörter in TListBox fett zeichnen
 
Könnte mir evtl. jemand mal ein beispiel zu den fetten Wörtern in der TListBox geben, irgendwie kriege ich das nicht mal in ansätzen richtig hin.
Danke ;D

Dennis07 4. Mai 2013 10:39

AW: Einzelne Wörter in TListBox fett zeichnen
 
Hallo, kann mir denn keiner hier helfen?
Außerdem stehe ich nach wie vor vor dem Problem mit den Tabsprüngen, die beim Draw-en nicht richtig angezeigt werden. Meine Suchen bisher waren leider erfolglos.
MFG

jaenicke 5. Mai 2013 06:05

AW: Einzelne Wörter in TListBox fett zeichnen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Mach es dir doch nicht so schwer... ich habe dir oben schon eine sehr einfache Lösung gepostet... ein Beispiel, folgender Text in der TJvHTListBox:
Zitat:

<b>Dennis:</b><ind=70>Test</ind>
Sebastian:<ind=70>Test2</ind>
Noch jemand:<ind=70>Ihr seid ja langweilig</ind>
<b>Dennis:</b><ind=70>Klappe</ind>
Ansonsten hat Luckie oben schon geschrieben wie Tabs korrekt angezeigt werden, so ca., bisschen Feintuning ist noch nötig: :wink:
Delphi-Quellcode:
procedure TForm246.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
const
  TextToHighlight = 'Dennis:';
var
  MyListBox: TListBox;
  CurrentItem: string;
  CurrentRect: TRect;
  CurrentPaintLeft: Integer;
  FormatValue: Integer;
begin
  MyListBox := Control as TListBox;
  CurrentItem := MyListBox.Items[Index];
  CurrentRect := Rect;
  FormatValue := DT_LEFT or DT_EXPANDTABS or DT_TABSTOP;
  LongRec(FormatValue).Bytes[1] := 14; // Tabbreite in Buchstaben
  if AnsiSameText(Copy(CurrentItem, 1, Length(TextToHighlight)), TextToHighlight) then
  begin
    Delete(CurrentItem, 1, Length(TextToHighlight));
    DrawText(MyListBox.Canvas.Handle, CurrentItem, Length(CurrentItem), CurrentRect, FormatValue); // erst den Text dahinter
    MyListBox.Canvas.Font.Style := [fsBold];
    DrawText(MyListBox.Canvas.Handle, TextToHighlight, Length(TextToHighlight), CurrentRect, FormatValue); // nun den Namen vorne
  end
  else
    DrawText(MyListBox.Canvas.Handle, CurrentItem, Length(CurrentItem), CurrentRect, FormatValue);
end;
Heraus kommt dann das (links: TJvHTListBox mit obigem Text, rechts: selbst gezeichnet):
Anhang 39164

Dennis07 5. Mai 2013 18:35

AW: Einzelne Wörter in TListBox fett zeichnen
 
Hm, danke schonmal.
Wieso erstellst du eine neue TListBox ("MyListbox")?
Wir haben doch schon eine?

jaenicke 5. Mai 2013 19:30

AW: Einzelne Wörter in TListBox fett zeichnen
 
Die TListBox wird im Sender als TWinControl übergeben, das hat aber keinen Canvas. Also caste ich den Sender auf TListBox, wobei as vorher prüft, ob das auch wirklich eine TListBox ist.
So kann der Code benutzt werden ohne eine bestimmte TListBox anzusprechen, ich bekomme sie ja im Sender.

Eine neue erstellt wird da nirgends.

Dennis07 5. Mai 2013 22:09

AW: Einzelne Wörter in TListBox fett zeichnen
 
hm, kann ich nicht einfach statt dem MyListBox da die Listbox einsetzen, mit der ich das mache?
Also ich habe ja schon im OI eine Listbox platziert, und mit der will ich das auch machen.
Wenn ich die also mit Namen anspreche, wird diese ja nicht als WinControl übergeben, sondern als TListBox.
Falls das der Grund für die neue TListBox war, so müsste dies eigentlich auch funktionieren, oder?

jaenicke 6. Mai 2013 09:21

AW: Einzelne Wörter in TListBox fett zeichnen
 
Zitat:

Zitat von Dennis07 (Beitrag 1214247)
Also ich habe ja schon im OI eine Listbox platziert, und mit der will ich das auch machen.

Es gibt keine neue Listbox... lass es einfach wie es ist und probiere es aus...
Ich habe die auch im OI gesetzt.

Das OnDrawItem bekommt diese Listbox als Sender übergeben, aber als Vorfahrtyp, nicht konkret als TListBox. Deshalb muss der Typ noch auf TListBox gecastet werden, damit man als TListBox damit arbeiten kann. Das bleibt dabei aber immer noch die selbe Listbox.

Dennis07 6. Mai 2013 22:29

AW: Einzelne Wörter in TListBox fett zeichnen
 
Achso, das war mir noch nicht so ganz klar gewesen.
Werde ich gleich morgen ausprobieren, danke.

MFG

Dennis07 9. Mai 2013 01:17

AW: Einzelne Wörter in TListBox fett zeichnen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hm, also entweder habe ich beim copy&paste erheblich was falsch gemacht, oder es funktioniert nicht.
Der Quelltext, so wie beschrieben, kann gar nicht funktionieren, da DrawText den HighlightText als PChar benötigt.
Und selbst wenn man das Problem dann behoben hat, so hat das Resultat kaum etwas mit dem gemeinsam, was ich brauche.

1. Der Text wird nicht ge-highlighted.
2. Das einzige, was sich ändert ist, dass ich nun so hässliche permanente FocusRects überall habe, und der Selected-Hintergrundfokus nicht über die Gesamte Breite verläuft.

(Screenshot beiliegend)

Danke trotzdem bis hierher.

jaenicke 9. Mai 2013 06:31

AW: Einzelne Wörter in TListBox fett zeichnen
 
Das mit dem PChar liegt daran, dass du Delphi 7 hast, darauf hatte ich nicht weiter geachtet. Damals (ist ja nun immerhin 11 Jahre alt) gab es die Stringversion von DrawText noch nicht.
Das mit der Markierung war noch ein Fehler, da fehlte ein FillRect um die Markierung aufzuräumen.

Mit Delphi 7 funktioniert es bei mir so:
Delphi-Quellcode:
procedure TForm246.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
const
  TextToHighlight = 'Dennis:';
var
  MyListBox: TListBox;
  CurrentItem: string;
  CurrentRect: TRect;
  CurrentPaintLeft: Integer;
  FormatValue: Integer;
begin
  MyListBox := Control as TListBox;
  CurrentItem := MyListBox.Items[Index];
  CurrentRect := Rect;
  MyListBox.Canvas.FillRect(Rect);
  FormatValue := DT_LEFT or DT_EXPANDTABS or DT_TABSTOP;
  LongRec(FormatValue).Bytes[1] := 14; // Tabbreite in Buchstaben
  if AnsiSameText(Copy(CurrentItem, 1, Length(TextToHighlight)), TextToHighlight) then
  begin
    Delete(CurrentItem, 1, Length(TextToHighlight));
    DrawText(MyListBox.Canvas.Handle, PChar(CurrentItem), Length(CurrentItem), CurrentRect, FormatValue); // erst den Text dahinter
    MyListBox.Canvas.Font.Style := [fsBold];
    DrawText(MyListBox.Canvas.Handle, PChar(TextToHighlight), Length(TextToHighlight), CurrentRect, FormatValue); // nun den Namen vorne
  end
  else
    DrawText(MyListBox.Canvas.Handle, PChar(CurrentItem), Length(CurrentItem), CurrentRect, FormatValue);
end;

Dennis07 9. Mai 2013 13:26

AW: Einzelne Wörter in TListBox fett zeichnen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ehm, zumindest danke für die Mühe bis hierher.
Zuerst die gute Nachricht: Die optischen "Zwischenfälle" sind nun behoben, es funktioniert nun wieder alles.
Nur leider wird auch nichts ge-highlighted (siehe Screenshot).

jaenicke 9. Mai 2013 18:12

AW: Einzelne Wörter in TListBox fett zeichnen
 
Naja, die Abfrage, ob der Text in der Zeile vorkommt, musst du schon anpassen...
Delphi-Quellcode:
if AnsiSameText(Copy(CurrentItem, 1, Length(TextToHighlight)), TextToHighlight) then
// ...
Das war ja nur ein Beispiel, in dem wie im Screenshot zu sehen der Text "Dennis:" am Anfang der Zeile steht...

Dennis07 11. Mai 2013 01:27

AW: Einzelne Wörter in TListBox fett zeichnen
 
Hey, danke, jetzt hat alles funktioniert.
Habe gerade noch mal ~6h dran gesessen, und es scheint alles zu funktionieren.
Vielen Dank für die Hilfe.

MFG


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:24 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-2025 by Thomas Breitkreuz