Autor |
Beitrag |
Chris1308
      
Beiträge: 220
Win XP Prof.
D2005 Prof, D7 Prof, D7 Pers
|
Verfasst: Do 11.07.02 20:42
Hi @all!
Wie kann ich einer Listbox eine waagerechte Scrollbar zuweisen?
Chris1308
|
|
DaDoc
      
Beiträge: 27
Win 2000, Linux
D2005 Prof
|
Verfasst: Fr 12.07.02 08:26
z.B. mit
Quelltext 1:
| SendMessage(Listbox.Handle, LB_SetHorizontalExtent, BreiteInPixel, LongInt(0)); |
Sobald die Listbox kleiner als "BreiteInPixel" ist, wird eine horizontale ScrollBar angezeigt, der so ausgelegt ist, daß man damit den Bereich von "BreiteInPixel" überschauen kann. Dazu muß man aber natürlich erstmal wissen, wie breit der "breiteste" Eintrag in Pixel ist (mit aktuellen Font) ...
Sven
|
|
Chatfix
      
Beiträge: 1583
Erhaltene Danke: 10
Win 10, Win 8, Win 7, Win Vista, Win XP
VB.net (VS 2015), MsSQL (T-SQL), HTML, CSS, PHP, MySQL
|
Verfasst: Mo 15.07.02 15:06
man sollte vieleicht doch die such-funktion des forums nutzen.. ichhatte das gleiche problem..
die lösung findest du hier:
www.delphi-forum.de/viewtopic.php?t=207
EDIT: Link aktualisiert, war noch auq.de
_________________ Gehirn: ein Organ, mit dem wir denken, daß wir denken. - Ambrose Bierce
Zuletzt bearbeitet von Chatfix am Do 21.04.05 14:38, insgesamt 1-mal bearbeitet
|
|
Prof. Dachs
Hält's aus hier
Beiträge: 11
Win 2000 SP4
D7 Pers
|
Verfasst: Do 21.04.05 13:51
Hallo,
ich habe gerade die Funktion SendMessage ausprobiert. Das hat aber nicht funktioniert, weil LB_SetHorizontal ein "undeclared identifier" ist. Ich habe es auch mit Listbox1.Perform ausprobiert, selber Fehler. Kann das daran liegen dass ich mit Delphi 7 Personal arbeite? Oder an was sonst?
Danke schon im Voraus,
Markus
|
|
DaDoc
      
Beiträge: 27
Win 2000, Linux
D2005 Prof
|
Verfasst: Do 21.04.05 14:25
Die Deklaration von "LB_SETHORIZONTALEXTENT" befindet sich in der Datei "Messages".
Btw.: Schau mal nach, ob deine Listbox die Eigenschaft "ScrollWidth" im Objektinspektor hat. Damit läst sich auch eine horizontale ScrollBar einblenden, wenn die Breite der Einträge (in Pixel) größer als die Breite der Listbox ist.
Sven
_________________ Das Denken ist die schwierigste Arbeit für einen Menschen. Deswegen beschäftigen sich ja auch nur so wenige damit...
|
|
Prof. Dachs
Hält's aus hier
Beiträge: 11
Win 2000 SP4
D7 Pers
|
Verfasst: Do 21.04.05 14:38
Mit der Einbindung der Unit Messages hat SendMessage jetzt funktioniert. thx@DaDoc.
Mit Scrollwidth hab ich des erst nich so ganz gepeilt, aber jetzt(nachdem ichs nochmal ausprobiert hab), funktioniert des auch). Also thx nochmal.
|
|
DaDoc
      
Beiträge: 27
Win 2000, Linux
D2005 Prof
|
Verfasst: Do 21.04.05 14:51
Laut QuellCode von TListBox wird beim Setzen von "ScrollWidth" wird auch nichts anderes gemacht, als ein "SendMessage(Handle, LB_SETHORIZONTALEXTENT, Value, 0)". Bin ich zuerst auch nicht darüber gestolpert...
Sven
_________________ Das Denken ist die schwierigste Arbeit für einen Menschen. Deswegen beschäftigen sich ja auch nur so wenige damit...
|
|
Dibelius
      
Beiträge: 64
|
Verfasst: Fr 03.04.09 21:03
*Uralt-Thread ausgrab*
ich hab nach diesem Tutorial für eine Listbox eine horizontale Scrollbar eingefügt. Funktioniert auch alles wunderbar... bis auf die Tatsache, dass sich gleiches Prinzip nicht auf eine zweite Listbox anwenden lässt, die ebenfalls in Form1 ist. Ich hab es sowohl mit gleichen als auch mit unterschiedlichen Variablen für die Scrollbar-Breite versucht. Klappte bisher alles nicht.
Kann mir da jemand eienn heißen Tipp geben?
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Fr 03.04.09 21:11
Dibelius hat folgendes geschrieben : | *Uralt-Thread ausgrab*
Kann mir da jemand eienn heißen Tipp geben? |
Versuchs mal damit:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| Procedure TFormX.SetHorizontalScrollBar(lb : TListBox); var j, MaxWidth,tmp: integer; begin MaxWidth := 0; tmp := 0; for j := 0 to lb.Items.Count - 1 do if MaxWidth < lb.Canvas.TextWidth(lb.Items[j]) then begin MaxWidth := lb.Canvas.TextWidth(lb.Items[j]); If MaxWidth > tmp then tmp := MaxWidth; end; SendMessage(lb.Handle,LB_SETHORIZONTALEXTENT,MaxWidth+300,0); end; |
Gruß delphi10
Edit. Ach ja, es kommt auf die Übergabe der Variable TListBox (Zeile1) an. Alles andere ist eigentlich genau so wie schon oben geschrieben.
SetHorizontalScrollBar(ListBox1);
SetHorizontalScrollBar(ListBox2); und so weiter...
_________________ Salus populi suprema lex esto
|
|
Dibelius
      
Beiträge: 64
|
Verfasst: Sa 04.04.09 13:49
uh, danke erstmal.
Aber irgendwie hab ich mit der Prozedur mehr Probleme. Erstmal haut das auch wieder nur für eine Listbox hin, obwohl ich als Parameter natürlich die jeweils richtige Listbox übergebe. Zudem seh ich die Items in der Listbox nun gar nicht mehr erst und es kommt zu unschönen Darstellungsfehlern beim Scrollen. Ist nicht so das Wahre :/
/EDIT:
Ich hab die Prozedur aus dem Tut nochmal abgekapselt von der ListBox.OnDrawItem Methode
Delphi-Quelltext 1: 2: 3: 4: 5:
| private flbHorzScrollWidth, flbHorzScrollWidth2: Integer; procedure AutoSizeListBox(TargetBox: TListBox; Index: integer; Rect: TRect; ScrollWidth: integer); |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.AutoSizeListBox(TargetBox: TListBox; Index: integer; Rect: TRect; ScrollWidth: integer); var Len: integer; NewText: string; begin NewText := TargetBox.Items[Index];
with TargetBox.Canvas do begin FillRect(Rect); TextOut(Rect.Left + 1, Rect.Top, NewText); Len := TextWidth(NewText) + Rect.Left + 3; if Len > ScrollWidth then begin ScrollWidth := Len; TargetBox.Perform(LB_SETHORIZONTALEXTENT, ScrollWidth, 0 ); end; end; end; |
Und dann beiden Listboxes im OI unter Events > OnDrawItem das der zweiten zugewiesen.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.ListBox2DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin case (Control as TListBox).Tag of 1: AutoSizeListBox(ListBox1, Index, Rect, flbHorzScrollWidth); 2: AutoSizeListBox(ListBox2, Index, Rect, flbHorzScrollWidth2); end; end; |
Leider funktioniert auch das wieder nur für eine Listbox (die mit Tag = 2), unabhängig davon, ob ich den Parameter "flbHorzScrollWidth" nur für eine oder für beide Listboxes verwende.
Das Problem liegt wohl woanders. Und zwar hab ich gerade mal den Code für die erste Listbox angepasst und ein showMessage eingefügt (in beiden Listboxes ist bei Programmstart zurzeit schon was eingetragen, was die Breite jeweils überschreitet).
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin case (Control as TListBox).Tag of 1: showMessage('Test'); 2: AutoSizeListBox(ListBox2, Index, Rect, flbHorzScrollWidth2); end; end; |
Die showMessage bleibt aus... bei der 2. klappt es und ich versteh einfach nicht, warum...
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Sa 04.04.09 16:17
 OnDrawItem? Meinst du nicht dass das ein winziges bisschen zu häufig ist?  Ändere die Größe des Scrollbalkens doch beim Einfügen oder Löschen von Einträgen einmalig
Edit: Delphi-Hilfe zu OnDrawItem: | Mit einer Ereignisbehandlungsroutine für OnDrawItem können Sie die Einträge von Listenfeldern zeichnen, deren Eigenschaft Style den Wert lbOwnerDrawFixed, lbOwnerDrawVariable oder lbVirtualOwnerDraw hat. |
OnDrawItem tritt nur auf, wenn du Listbox.Style auf eine der OwnerDraw-Optionen gesetzt hast.
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
Dibelius
      
Beiträge: 64
|
Verfasst: Sa 04.04.09 17:41
Würde ich gern so machen, wenn ich wüsste, was ich als "Rect" und "Index" an die AutoSizeListBox-Prozedur übergeben müsste...
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Sa 04.04.09 18:00
Andere Frage: Hat deine Listbox eine Eigenschaft ScrollWidth? Das ist nämlich das gleiche, nur gekapselt in einer simplen Zuweisung (Meine unter Delphi7 hat sie.) Falls nicht, kannst du die markierte Stelle mit TargetBox.Perform(LB_SETHORIZONTALEXTENT, ScrollWidth, 0 ); ersetzen.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.AutoSizeListBox(TargetBox: TListBox); var Len, i: integer; NewText: string; begin Len := TargetBox.Canvas.TextWidth(TargetBox.Items[0]); for i := 0 to TargetBox.Items.Count - 1 do begin NewText := TargetBox.Items[i]; if TargetBox.Canvas.TextWidth(NewText) > Len then Len := TargetBox.Canvas.TextWidth(NewText); end;
TargetBox.ScrollWidth := Len + 10; end; |
Aufruf: AutosizeListbox(Listbox1);
Problem: Etwas langsam. Spürt man aber nicht wirklich bei 2000 Einträgen, denke ich. Einfach immer dann aufrufen, wenn ein Item gelöscht oder hinzugefügt wird. Wenn man's schneller haben will, kann man zunächst TargetBox.Items in eine TStringList schreiben und mit dieser arbeiten, ich hab das mal ausprobiert, kann durchaus schneller gehen, dadurch.
Wegen "Nicht in onDrawItem aufrufen": Da hab ich den Code falsch betrachtet, der ist für onDrawItem gedacht, definitiv.
Wenn der alte Code nicht funktioniert, schau mal ob du beide Listboxes auf Style = dsOwnerDraw[irgendwas] gestellt hast, wenn nicht, wird das onDrawItem Ereignis garnicht ausgelöst
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Sa 04.04.09 18:23
Dibelius hat folgendes geschrieben : | Würde ich gern so machen, wenn ich wüsste, was ich als "Rect" und "Index" an die AutoSizeListBox-Prozedur übergeben müsste... |
Delphi-Quelltext
Zitat: | Die showMessage bleibt aus... bei der 2. klappt es und ich versteh einfach nicht, warum... |
Hat denn eine ListBox den Tag= 1?
Wenn Du wirklich im Inspector für die ListBox den Style auf lbOwnerDrawVariable gestellt hast, musst du gar nichts übergeben und auch nicht explizit aufrufen. Das geht mit der Ausgabe eines Items ganz automatisch. Ist denn das Ereignis "OnDrawItem" richtig gesetzt mit "ListBox2DrawItem"? Schau Dir mal www.delphipraxis.net...m+listboxstring.html an.
_________________ Salus populi suprema lex esto
|
|
Dibelius
      
Beiträge: 64
|
Verfasst: Sa 04.04.09 18:39
JayEff hat folgendes geschrieben : | Wenn der alte Code nicht funktioniert, schau mal ob du beide Listboxes auf Style = dsOwnerDraw[irgendwas] gestellt hast, wenn nicht, wird das onDrawItem Ereignis garnicht ausgelöst |
argh, ich hatte wohl Tomaten auf den Augen. Danke, genau das war es, warum onDrawItem bei der einen Box nicht aufgerufen wurde. Kleiner Fehler, große Wirkung ^^
achso, eine Sache noch (nur zum Verständnis):
Wo wird überhaupt der Parameter "ScrollWidth" initialisiert? (s. meinen Code oben)
Ich deklariere es da zwar unter private, aber dann vergleicht die Prozedur plötzlich den Wert mit "Len" und erst bei Erfolg wird ein Wert zugewiesen. Welchen Wert hat "ScrollWidth" vor dem Vergleich?
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Sa 04.04.09 18:56
Dibelius hat folgendes geschrieben : | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.AutoSizeListBox(TargetBox: TListBox; Index: integer; Rect: TRect; ScrollWidth: integer); var Len: integer; NewText: string; begin NewText := TargetBox.Items[Index];
with TargetBox.Canvas do begin FillRect(Rect); TextOut(Rect.Left + 1, Rect.Top, NewText); Len := TextWidth(NewText) + Rect.Left + 3; if Len > ScrollWidth then begin ScrollWidth := Len; TargetBox.Perform(LB_SETHORIZONTALEXTENT, ScrollWidth, 0 ); end; end; end; |
Delphi-Quelltext 1:
| AutoSizeListBox(ListBox1, Index, Rect, flbHorzScrollWidth); | |
Die markierten Stellen sollten das erklären (auch wenn ich mich etwas wundere, da ScrollWith kein var-Parameter ist): Die globale Variable flbHorzScrollWidth speichert die ScrollWidth der entsprechenden Listbox wie sie vor dem Aufruf der Autosize-Prozedur ist. Dieser Wert wird der Autosize übergeben. In dieser wird für das gerade gezeichnete Item der Listbox ermittelt, wie breit das Item im Endeffekt ist. Ist in flbHorzScrollWidth bereits ein größerer Wert als der gerade ermittelte, muss keine Änderung der ScrollWidth durchgeführt werden. Falls doch, so setzen wir ScrollWidth auf den ermittelten Wert und ändern die größe des horizontalen Scrollbalkens. (Die Perform-Methode tut das). Ausserdem übernimmt die Autosize-Prozedur das Zeichen des Items selber, was auch nötig ist, da die Listbox ja auf OwnerDraw steht. Das geschieht über FillRect und TextOut (Rechteck mit Farbe füllen, dann Text draufschreiben).
Funktioniert die Listbox dann noch so wie gewohnt? Ich meine, ist das markierte Item blau hinterlegt? Ich sehe nämlich nirgends im Code, dass im onDrawItem der Parameter State auf "Selected" überprüft wird
Edit: Globale Integer-Variablen werden normalerweise mit 0 initialisiert, worauf man sich aber nie verlassen sollte  In diesem Fall vermute ich, dass beim allerersten Aufruf der Autosize-Prozedur 0 in der Variable steht, was im Prinzip genau das ist, was wir hier wollen.
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
Dibelius
      
Beiträge: 64
|
Verfasst: Sa 04.04.09 19:12
Ok, danke für die Aufklärung. Ich wusste nicht, dass globale Variablen mit 0 initialisiert werden. Ich hab das bisher immer eigenhändig getan und werde wohl auch dabei bleiben.
JayEff hat folgendes geschrieben : | Funktioniert die Listbox dann noch so wie gewohnt? Ich meine, ist das markierte Item blau hinterlegt? Ich sehe nämlich nirgends im Code, dass im onDrawItem der Parameter State auf "Selected" überprüft wird  |
Ja, funktioniert alles. Ich stelle da kein Unterschied zur "normalen" Listbox fest, bis auf die Textausgabe, die man m.H. von Canvas relativ frei gestalten könnte, wenn man das will. Selected sieht man aber.
btw: in deiner Prozedur fehlt die Textausgabe noch.
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Sa 04.04.09 19:26
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
|