![]() |
ListView Breite der letzten Spalte beim Resize der Form
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo in die Gemeinde :).
Gegeben sei ein TListView mit Anchors an allen 4 Kanten auf einem TForm. Die letzte Spalte des ListView soll immer die restliche Breite des ListView einnehmen, wenn das Formular in der Breite verändert wird. Ich will also eine Art TListColumn.AutoSize anhand der Breite statt des enthaltenen Texts. Dafür bietet sich das OnResize-Event des ListView an.
Delphi-Quellcode:
Probleme:
procedure TfmMain.ListViewResize(Sender: TObject);
var Llv: TListView; Lcolwidth, Ltotalcolwidth, i: integer; Lcol: TListColumn; begin Llv:= nil; if Sender is TListView then Llv:= (Sender as TListView); if NOT Assigned(Llv) then Exit; Ltotalcolwidth:= 0; for i:= 0 to Pred(Llv.Columns.Count) do begin Inc(Ltotalcolwidth, Llv.Columns[i].Width); end; Lcol:= Llv.Columns[Llv.Columns.Count-1]; Lcolwidth:= Llv.ClientWidth - Ltotalcolwidth - Lcol.Width; if (Lcolwidth >= Lcol.MinWidth) then Lcol.Width:= Lcolwidth; end;
Erreichen will ich Folgendes:
Grüße Dalai |
AW: ListView Breite der letzten Spalte beim Resize der Form
Setze doch die Breite der letzten Spalte einfach auf LVSCW_AUTOSIZE.
|
AW: ListView Breite der letzten Spalte beim Resize der Form
Zitat:
Delphi-Quellcode:
. Ich will aber die gesamte verbleibende Breite des ListView ausnutzen.
TListColumn.AutoSize:= True;
Mit
Delphi-Quellcode:
spart man sich zwar die Iteration über die Spalten und die Berechnung der verbleibenden Breite, aber es führt zum selben Ergebnis wie der Code oben, mit Flackern und allem :(.
ListView_SetColumnWidth(Llv.Handle, Lcol.Index, LVSCW_AUTOSIZE_USEHEADER);
Grüße Dalai |
AW: ListView Breite der letzten Spalte beim Resize der Form
Das geht doch mit letzte Spalte.Width := -2 oder nicht?
|
AW: ListView Breite der letzten Spalte beim Resize der Form
Nein,
Delphi-Quellcode:
erzeugt ebenfalls nicht das gewünschte Verhalten. Die letzte Spalte wird beim Verbreitern nicht auf den verbleibenden Platz vergrößert. Zudem soll die letzte Spalte nicht schmaler werden, wenn die anderen Spalten vergrößert werden.
Lcol:= ColumnHeaderWith;
Grüße Dalai |
AW: ListView Breite der letzten Spalte beim Resize der Form
Liste der Anhänge anzeigen (Anzahl: 2)
Zitat:
Ich selbst verwende meistens die Virtual TreeView. Damit kann man viel mehr selbst anpassen. Allerdings läuft die aktuelle Version auch nur mit aktuellen Delphiversionen, d.h. du müsstest eine passende Version nutzen. Die alte Version im Anhang lief ab Delphi 4. |
AW: ListView Breite der letzten Spalte beim Resize der Form
Ich weiß nicht, wie ich es genauer oder anders beschreiben soll, was ich erreichen will, als ich das im OP bereits getan habe. Setzt man AutoSize der letzten Spalte auf True, nimmt sie den verbleibenden Platz ein. Bei Größenänderung des ListView wird sie mit angepasst. All das ohne Flackern. Soweit so schön.
Vergrößert man eine der anderen Spalten, wird der horizontale Scrollbalken eingeblendet, was auch noch in Ordnung und gewünscht ist. Jetzt kommt das große Aber: Ändert man anschließend die Breite des Formulars (und damit des ListViews), wird die letzte Spalte schmaler und der Scrollbalken verschwindet. Das will ich nicht! Die letzte Spalte soll ihre Breite behalten, solange der Scrollbalken sichtbar ist. Danach darf/soll sie wieder der Breite des ListView folgen. Vielleicht wird es anhand eines Beispiels deutlicher: Vier Spalten mit Breiten 100, 40, 40 und 300. Breite der ersten Spalte wird auf 300 erhöht, wodurch der Scrollbalken erscheint (OK). Anschließend wird die Breite des Formulars/ListViews geändert und danach ist die letzte Spalte nur noch 100 breit und der Scrollbalken weg; sie soll aber bei 300 bleiben, bis das ListView so breit gemacht wurde, dass der Scrollbalken ausgeblendet wird. Grüße Dalai |
AW: ListView Breite der letzten Spalte beim Resize der Form
Das mit dem Beibehalten der Breite hatte ich falsch verstanden.
Also bei mir flackert mit deinem Code gar nichts und die Scrolleiste bleibt auch nicht so sichtbar wie in deinem Screenshot. Mit der Virtual TreeView fährst du mit solchen speziellen Wünschen aber sicher am besten, denn dort kannst du das Feature direkt in die Breitensteuerung der Spalte einbauen, aber auch von außen sollte das machbar sein. |
AW: ListView Breite der letzten Spalte beim Resize der Form
Erstmal ein Dankeschön fürs Mitdenken und Mitmachen an alle Beteiligten :).
Inzwischen hab ich die Sache für mich zufriedenstellend gelöst. Ich stelle mal hier den Code mit etwas Erklärung ein, damit es auch anderen weiterhelfen kann. Die Grundlage bilden die Ereignisse OnResize und OnCanResize des ListView. OnCanResize wird vor dem Resize eines Controls ausgelöst, OnResize danach. OnResize verwende ich schon von Beginn an, OnCanResize ist in TControl als protected property deklariert und daher nicht direkt zuweis- und nutzbar. Um dies zu umgehen, hab ich mir eine kleine Unit geschrieben:
Delphi-Quellcode:
Hinweis:
unit VCLHacks;
interface uses ComCtrls, Controls; type TMyListView = class(TListView) end; procedure ListView_SetOnCanResize(const AListView: TListView; const AOnCanResize: TCanResizeEvent); implementation procedure ListView_SetOnCanResize(const AListView: TListView; const AOnCanResize: TCanResizeEvent); begin TMyListView(AListView).OnCanResize:= AOnCanResize; end; end. Die nachfolgenden Code-Auszüge sind fürs Forum vereinfachte und verkürzte Beispiele. Im eigentlichen Programm gibt viele in einer TList gespeicherte ListViews, die alle dieselben Eigenschaften und Events zugewiesen bekommen. Beim Starten werden die Eigenschaften und Ereignisse zugewiesen:
Delphi-Quellcode:
Die Behandlung der Ereignisse sieht so aus:
procedure TfmMain.FormCreate(Sender: TObject);
begin FScrollBarSize:= Windows.GetSystemMetrics(SM_CXVSCROLL); if ListView1.Columns.Count > 0 then ListView1.Columns[ListView1.Columns.Count-1].AutoSize:= True; end; procedure TfmMain.FormShow(Sender: TObject); begin SetListViewEvents(ListView1); end; procedure TfmMain.SetListViewEvents(const AListView: TListView); begin if NOT Assigned(AListView) then Exit; AListView.OnResize:= ListViewResize; ListView_SetOnCanResize(AListView, ListViewCanResize); end;
Delphi-Quellcode:
AutoSize der letzten Spalte wird ausgeschaltet, wenn die Summe der Breite aller Spalten größer ist als die sichtbare Breite des ListView (ClientWidth). AutoSize wird wieder aktiviert, wenn die Summe der Breite der Spalten maximal so groß ist wie ClientWidth zulässt. Dadurch wird die letzte Spalte nicht mehr schmaler, wenn andere Spalten vergrößert werden und anschließend das ListView in der Breite verändert wird.
procedure TfmMain.ListViewCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);
var Llv: TListView; Lcol: TListColumn; Ltotalcolwidth, i: integer; begin if FListViewItemsUpdating then Exit; if NOT (Sender is TListView) then Exit; Llv:= TListView(Sender); Ltotalcolwidth:= 0; for i:= 0 to Pred(Llv.Columns.Count) do Inc(Ltotalcolwidth, ListView_GetColumnWidth(Llv.Handle, i)); Lcol:= Llv.Columns[Llv.Columns.Count-1]; Lcol.AutoSize:= ((Ltotalcolwidth - FScrollBarSize) <= Llv.ClientWidth); end; Da die ListViews während der Programmlaufzeit mit immer wieder neuen Daten gefüllt werden können, erscheint ggf. ein vertikaler Scrollbalken, was einen horizontalen Scrollbalken aktiviert. Um das zu behandeln, mache ich mir das im OnShow zugewiesene OnResize-Ereignis zunutze:
Delphi-Quellcode:
Die letzte Spalte wird verkleinert, wenn die Summe aller Spaltenbreiten die ClientWidth des ListViews um eine Scrollbalken-Breite überschreitet. Dadurch verschwindet der horizontale Scrollbalken wieder.
procedure TfmMain.ListViewResize(Sender: TObject);
var Llv: TListView; begin Llv:= nil; if Sender is TListView then Llv:= (Sender as TListView); if Assigned(Llv) then ListViewAdjustLastColumnWidth(Llv); end; procedure TfmMain.ListViewAdjustLastColumnWidth(const AListView: TListView); var Ltotalcolwidth, Lcolwidth, i: integer; Lcol: TListColumn; begin if NOT Assigned(AListView) then Exit; Ltotalcolwidth:= 0; for i:= 0 to Pred(AListView.Columns.Count) do Inc(Ltotalcolwidth, ListView_GetColumnWidth(AListView.Handle, i)); Lcol:= AListView.Columns[AListView.Columns.Count-1]; Lcolwidth:= ListView_GetColumnWidth(AListView.Handle, Lcol.Index); if ((Ltotalcolwidth - FScrollBarSize) = AListView.ClientWidth) then begin Lcolwidth:= Lcolwidth - FScrollBarSize; ListView_SetColumnWidth(AListView.Handle, Lcol.Index, Lcolwidth); Exit; end; // [...] end; Grüße Dalai |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:13 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