Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi mehrzeilige listbox-einträge (https://www.delphipraxis.net/89945-mehrzeilige-listbox-eintraege.html)

maddins 9. Apr 2007 01:18


mehrzeilige listbox-einträge
 
hi leute,

ich brauch mal wieder hilfe bei einem problem, dessen lösung bestimmt wieder ganz einfach und irgendwo versteckt ist...

und zwar würde ich gern mehrzeilige einträge in einer listbox machen, d.h. mehrere zeilen pro listbox.Item.text(). ich habs schon mit #13#10 (oder wars anders rum? k.a., ging beides nich ;-) )zwischen den texten probiert, aber alles, was er dann anzeigt, sind 2 unausgefüllte kästchen zwischen den 2 text-stückchen. außerdem hab ich noch mit listbox.itemheight rumgespielt, was allerdings keine veränderung gebracht hat.

sollte ich dafür überhaupt eine listbox verwenden? oder gibts da andere (vielleicht bessere) wege?
mit den späteren einträgen wollte ich dann auch arbeiten, d.h. durch doppelklicks o.ä. zum beispiel die einträge editieren (über ein formular mit showmodal) oder so.

vielen dank für eure ratschläge.

maddins

MrKnogge 9. Apr 2007 01:36

Re: mehrzeilige listbox-einträge
 
Moin,

ich würde dir da den VirtualStringTree von Mike Lischke empfehlen.

Gruß

Sunlight7 9. Apr 2007 03:36

Re: mehrzeilige listbox-einträge
 
Moin!

Du könntest auch im OwnerDraw selber zeichnen und mit AddObject Infos über die Items speichern.

marabu 9. Apr 2007 08:24

Re: mehrzeilige listbox-einträge
 
Guten Morgen,

hier wurde das Thema auch schon behandelt: Wordrap bei ListBoxen

Frohe Ostern

maddins 9. Apr 2007 18:52

Re: mehrzeilige listbox-einträge
 
danke erstmal.

es ist auf jeden fall schon mal ein schritt in die richtige richutng.

aber ich möchte egtl nicht den text in der listbox beliebig umbrechen, sondern ich möchte 3 zeilen text in einer listbox haben, nehmen wir mal an: dateiname, größe, abmessung einer bilddatei. dabei ist es egal, wenn eine der zeilen länger als die egtle breite der listbox ist. es kommt mir nur auf den umbruch der einzelnen zeilen an.

mit listbox.canvas lässt sich recht gut zeichnen, aber es entsteht ja in diesem fall nicht wirklich eine (listbox-)zeile, die man dann anklicken (markieren) und/oder bearbeiten kann. wenn ich ein neues item erstelle, wird ja die canvas irgendiwe überschrieben.

kann man da nich irgendwas kombienieren??

mfg, maddins

Sunlight7 9. Apr 2007 19:46

Re: mehrzeilige listbox-einträge
 
Liste der Anhänge anzeigen (Anzahl: 1)
Abend!

Du stellst Dir sowas vor?

Ich hab jetzt nur 1 Edit auf den Dateinamen, weil ich keinen Bedarf habe andere Eigenschaften zu editieren, aber es wäre nur eine Spielerei, mehrere Edits zu machen.

Edit: Nanu? Wo ist das Attachment abgeblieben :gruebel:
Nochmal...

SirThornberry 9. Apr 2007 19:57

Re: mehrzeilige listbox-einträge
 
und wie willst du dann sicherstellen das der Nutzer sieht das es sich um einen Eintrag handelt ohne das er erst den Text erfassen muss? Nutzerfreundlich ist es sicher nicht wenn man nicht mehr sieht wo ein Listboxeintrag anfängt und wo er aufhört.

maddins 9. Apr 2007 20:04

Re: mehrzeilige listbox-einträge
 
@ sunlight7

ahja - an genau sowas hab ich gedacht...



@ sir thornberry

also ich find das nich unübersichtlich. is doch ne gute möglichkeit, ne menge informationen gebündelt in einer liste anzuzeigen.

Sunlight7 9. Apr 2007 20:14

Re: mehrzeilige listbox-einträge
 
@SirThornberry: Ich hab das seit vielen Jahren für mich in Betrieb, das war nie für andere Nutzer gedacht...
Aber es würde schlicht genügen, entweder den Hintergrund mit Farbverlauf zu Zeichnen oder einfach einen fetten Strich zwischen den Items zu machen ;)

LAWn-M0W3R 9. Apr 2007 23:18

Re: mehrzeilige listbox-einträge
 
Hier noch eine Möglichkeit:

Du willst einfach nur mehrere Zeilen? Dann unterteile den jeweiligen String doch einfach in eine Art stringlist.
Also, wenn du da so ein neues item.Caption oder so einfügst, dann sagst du ihm einfach:
Delphi-Quellcode:
Caption := 'string1' + chr($0D) {Zeichen für Zeilenumbruch} + 'string2' + chr($0D) + 'string3';
Das sieht dann so aus:
Zitat:

string1
string2
string3
...und was die Benutzerfreundlichkeit angeht, so mach es wie Sunlight7 und bau nen Farbverlauf in die Paint-Prozedur!
Hoffe geholfen zu haben!
Schönen Abend noch und Grüße vom Max

Sunlight7 10. Apr 2007 00:27

Re: mehrzeilige listbox-einträge
 
Moin!

@maddins: Weil Du per PN anfragtest, jo, da muß man etwas Tricksen.

Wir basteln uns einen Record
Delphi-Quellcode:
type
  PItem=^TItem;
  TItem packed record
     FileName:String;
     FileSize:Int64;
     Comment:String;
     UndWasHaltSonstNoch:TIrgendwas;
  end;
Hinzufügen eines Items
Delphi-Quellcode:
   var Item:PItem;
...
   New(Item);
   If Item=nil then ... // Fehlerabfrage

   Item^.FileName:=...;
   Item^.FileSize:=...;
   Item^.Comment:=...;

   ListBox1.Items.AddObject(Item^.FileName, TObject(Item));
Anwendungsbeispiel
Delphi-Quellcode:
   var Item:PItem;
...
   Item:=PItem(ListBox1.Items.Objects[ListBox1.ItemIndex]);
   Canvas.TextOut(0, 0, Item^.FileName);
   Canvas.TextOut(0, 20, IntToStr(Item^.FileSize));
   Canvas.TextOut(0, 40, Item^.Comment);
Und net vergessen, den Speicher mit Dispose wieder frei zu geben ;)


Zitat:

Zitat von LAWn-M0W3R
und was die Benutzerfreundlichkeit angeht, so mach es wie Sunlight7 und bau nen Farbverlauf in die Paint-Prozedur!

Nicht in die Paint, in die OnDrawItem ;)

EDatabaseError 10. Apr 2007 00:32

Re: mehrzeilige listbox-einträge
 
Zitat:

Zitat von LAWn-M0W3R
Hier noch eine Möglichkeit:

Du willst einfach nur mehrere Zeilen? Dann unterteile den jeweiligen String doch einfach in eine Art stringlist.
Also, wenn du da so ein neues item.Caption oder so einfügst, dann sagst du ihm einfach:
Delphi-Quellcode:
Caption := 'string1' + chr($0D) {Zeichen für Zeilenumbruch} + 'string2' + chr($0D) + 'string3';
Das sieht dann so aus:
Zitat:

string1
string2
string3
...und was die Benutzerfreundlichkeit angeht, so mach es wie Sunlight7 und bau nen Farbverlauf in die Paint-Prozedur!
Hoffe geholfen zu haben!
Schönen Abend noch und Grüße vom Max

Das zeichen für Zeilenumbruch ist aber $0D + $0A!

Daraus folgt:

Caption := 's1' + #13+#10 + 's2';

(#13 = $0D und #10 = $0A)

Mfg

mkinzler 10. Apr 2007 07:19

Re: mehrzeilige listbox-einträge
 
Oder die Konstante sLineBreak verwenden.

maddins 12. Apr 2007 22:56

Re: mehrzeilige listbox-einträge
 
hallo,

danke für die hilfe.
zwar hab ich solch eine art der implementation noch nie gesehen :? , werds aber ausprobieren und gucken, was ich damit alles anstellen kann. :thumb:

bis dann
maddins

maddins 12. Apr 2007 23:26

Re: mehrzeilige listbox-einträge
 
also ich hab jetzt mal testweise folgendes gemacht:

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
 var eintrag:pitem;
begin
  new(eintrag);
  eintrag^.zeile1:='test1';
  eintrag^.zeile2:='test2';
  eintrag^.zeile3:='test3';

  ListBox1.Items.AddObject(eintrag^.zeile1, TObject(eintrag));

  eintrag:=PItem(ListBox1.Items.Objects[ListBox1.ItemIndex]);
  listbox1.Canvas.TextOut(0, 0, eintrag^.zeile1);
  listbox1.Canvas.TextOut(0, 20, eintrag^.zeile2);
  listbox1.Canvas.TextOut(0, 40, eintrag^.zeile3);
 end;
lieder bleibt er bei der zeile
Delphi-Quellcode:
eintrag:=PItem(......);
mit folgender fehlermeldung stehen:

"List index out of bounds (-1)"

wenn ich fortsetze ist zwar der eintrag da mit dem inhalt aus "zeile1" aber mehr auch nicht. die restlichen zeilen fehlen.

btw: was bewirken die ^ ??

maddins

Sunlight7 12. Apr 2007 23:39

Re: mehrzeilige listbox-einträge
 
Abend!

Die ^ sagen dem Compiler, das es sich bei der Variable um einem dynamischen Zeiger auf ein Object o.ä. handelt (besser kann ichs um diese Zeit net ausdrücken ^^)

Der Fehler liegt daren, das Du ListBox1.ItemIndex als Index verwendest Und ich mich zu wetten traue, das nicht in der ListBox markiert ist :zwinker:

Abgesehen, das es keinen Sinn macht, es in dem ButtonClick Ereignis Zu zeichnen, das wäre besser im OnDrawItem der ListBox aufgehoben, da hast Du dann auch den Index, welcher gerade zu Zeichnen ist und die Variable Rect, damit Du auch weist wohin es gezeichnet werden soll ;)

Sieh mal in die OH zum Thema Delphi-Referenz durchsuchenOnDrawItem, Da findest Du auch ein Beispiel dazu ;)

maddins 13. Apr 2007 10:45

Re: mehrzeilige listbox-einträge
 
Liste der Anhänge anzeigen (Anzahl: 1)
aha, jetz versteh ich langsam...

so sieht das jetz aus:

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
 var eintrag:pitem;
begin
  new(eintrag);
  eintrag^.zeile1:='test1';
  eintrag^.zeile2:='test2';
  eintrag^.zeile3:='test3';

  ListBox1.Items.AddObject(eintrag^.zeile1, TObject(eintrag));

end;


procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
  var item:pitem;
begin
   Item:=PItem(ListBox1.Items.Objects[Index]);
   listbox1.Canvas.TextOut(0, index*40+0, Item^.zeile1);
   listbox1.Canvas.TextOut(0, index*40+12, Item^.zeile2);
   listbox1.Canvas.TextOut(0, index*40+24, Item^.zeile3);

end;
gibts egtl auch nen mittel gegen diese etwas "komische" darstellung, wenn man auf die einträge klickt??

Sunlight7 13. Apr 2007 15:42

Re: mehrzeilige listbox-einträge
 
Jo gibt es, Du hast net das Beispiel der OH geguckt?

Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
   var Item:PItem;
begin
   // Die Variable Rect zeigt Dir den Bereich, wohin gezeichnet werden soll

   Item:=PItem(ListBox1.Items.Objects[Index]);
   Listbox1.Canvas.FillRect(Rect); // ! Bereich vorher löschen
   Listbox1.Canvas.TextOut(Rect.Left+1, Rect.Top+ 1, Item^.Zeile1);
   Listbox1.Canvas.TextOut(Rect.Left+1, Rect.Top+13, Item^.Zeile2);
   Listbox1.Canvas.TextOut(Rect.Left+1, Rect.Top+25, Item^.Zeile3);
end;

maddins 16. Apr 2007 23:49

Re: mehrzeilige listbox-einträge
 
Liste der Anhänge anzeigen (Anzahl: 1)
jo! das funktioniert soweit ganz gut...

allerdings scheint er immer noch beim scrollen durcheinander zu kommen!? :wall:

grüße
maddins

Sunlight7 17. Apr 2007 01:22

Re: mehrzeilige listbox-einträge
 
Moin!

Ja, der Screenshot is schön anzusehen, aber ohne zu wissen wie Dein Quellcode aussieht kann ich da nur schwer Fehler finden ;)

maddins 17. Apr 2007 21:12

Re: mehrzeilige listbox-einträge
 
oops! ich war nur schlampig...

hab doch die position zum zeichnen mit dem index errechnet und nich mit den eigenschaften von >>rect<<...

also ich denke, damit werd ich jetz erstmal klarkommen und nen bisschen experimentieren.

vielen dank nochmal für die hilfe. falls ich später noch fragen hab, werd ich die hier posten, ich wollt ja noch n paar klickereignisse implementieren und auch kleine bildchen zeichnen. aber davon hab ich ja hier schon beispiele in hülle und fülle gesehn.

bis dann + grüße
maddins

LinuxFan 6. Okt 2008 22:58

Re: mehrzeilige listbox-einträge
 
Hallo,

wo kommt die Funktion "Dispose(...)" rein?

hoika 7. Okt 2008 02:47

Re: mehrzeilige listbox-einträge
 
Hallo,

warum so kompliziert,
nimm einen TListView, da musst du gar nichts machen.

Delphi-Quellcode:
ListItem:= ListView.Items.Add;
ListItem.Caption:= 'Spalte 1';
ListItem.SubItems.Add('Spalte2');

Update:
Habe gerade "Bildchen zeichnen" gelesen
-> TVirtualTreeView, auch wenn der Anfang etwas kompliziert ist,
aber dafür gibt es Tutorials (Such-Funktion)


Heiko

LinuxFan 10. Okt 2008 18:32

Re: mehrzeilige listbox-einträge
 
Zitat:

Zitat von hoika
Hallo,

warum so kompliziert,
nimm einen TListView, da musst du gar nichts machen.

Delphi-Quellcode:
ListItem:= ListView.Items.Add;
ListItem.Caption:= 'Spalte 1';
ListItem.SubItems.Add('Spalte2');

Hier geht es um mehrZEILIGE ListBoxes. Nicht um mehrspaltige.

Für alle die es interessiert:
Delphi-Quellcode:
type
  TCodeInsightItem = record
                       ciType: string[255];
                       ciKey: string[255];
                       ciAttri: string[255];
                       ciReturn: string[255];
                       ciDesc: string[255];
                     end;

type
  PCodeInsightItem = ^TCodeInsightItem;

...........

procedure X ...;
var
  ciEntry: TCodeInsightItem;
  ciEntryP: PCodeInsightItem;
begin
  for i := 0 to lbxCodeInsight.Items.Count - 1 do
  begin
    ciEntryP := PCodeInsightItem(lbxCodeInsight.Items.Objects[i]);
    Dispose(ciEntryP);
  end;
  lbxCodeInsight.Items.Clear;
  for i := 0 to intBuffer - 1 do
  begin
    ... Definition von ciEntry ...
    New(ciEntryP);
    ciEntryP^.ciType := ciEntry.ciType;
    ciEntryP^.ciKey := ciEntry.ciKey;
    ciEntryP^.ciAttri := ciEntry.ciAttri;
    ciEntryP^.ciReturn := ciEntry.ciReturn;
    ciEntryP^.ciDesc := ciEntry.ciDesc;

    lbxCodeInsight.Items.AddObject(ciEntryP^.ciKey, TObject(ciEntryP));
  end;
end;

procedure TfrmMain.lbxCodeInsightDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  Entry: PCodeInsightItem;
  ciKeyWidth, ciAttriWidth: Integer;
begin
     Entry := PCodeInsightItem(Items.Objects[Index]);
     if ItemIndex <> Index then
       if Index mod 2 = 0 then Canvas.Brush.Color := $00FDF7EE else Canvas.Brush.Color := clWhite;
     Canvas.FillRect(Rect);
     Canvas.TextOut(Rect.Left+1, Rect.Top+1, Entry^.ciType);
     Canvas.Font.Style := [fsBold];
     Canvas.TextOut(Rect.Left+60, Rect.Top+1, Entry^.ciKey);
     ciKeyWidth := Canvas.TextWidth(Entry^.ciKey);
     Canvas.Font.Style := [];
     Canvas.TextOut(Rect.Left+60+ciKeyWidth, Rect.Top+1, ' (' + Entry^.ciAttri + ')');
     ciAttriWidth := Canvas.TextWidth(' (' + Entry^.ciAttri + ')');
     if Entry^.ciReturn <> '' then Canvas.TextOut(Rect.Left+60+ciKeyWidth+ciAttriWidth, Rect.Top+1, ' : ' + Entry^.ciReturn);
     Canvas.Font.Style := [fsBold];
     Canvas.Font.Size := 8;
     Canvas.TextOut(Rect.Left+5, Rect.Top+18, Entry^.ciDesc);
   end;
end;
http://home.viathinksoft.de/victor/d...ne_listbox.jpg

Sunlight7 10. Okt 2008 18:50

Re: mehrzeilige listbox-einträge
 
Zitat:

Zitat von LinuxFan
Hallo,

wo kommt die Funktion "Dispose(...)" rein?

Also Dispose rufst Du überall auf, wenn einzelne oder mehrere/alle Objecte aus der Liste entfernt werden.
  • .Delete(x);
  • .Clear;
  • und im Destructor
  • Genau genommen auch beim Zuweisen von Items.Text
Am einfachsten ist es, Dir eine neue Klasse abzuleiten, denn da kannst Du es einfach überschreiben und brauchst Dich im eigentlichem QT nicht mehr drum zu kümmern.

MfG, Sun

hoika 11. Okt 2008 08:23

Re: mehrzeilige listbox-einträge
 
Hm,

oha, mehrzeilig.

virtual treeview + wordrwap


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:41 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