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:
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.
Hinweis:
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:
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;
Die Behandlung der Ereignisse sieht so aus:
Delphi-Quellcode:
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;
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.
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:
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;
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.
Grüße
Dalai