From 28ffba2df0e171fbfa8af66146382f718bbaac0c Mon Sep 17 00:00:00 2001 From: Martin Prikryl Date: Tue, 25 Mar 2025 13:38:41 +0000 Subject: [PATCH] =?UTF-8?q?Issue=202361=20=E2=80=93=20Layout=20problems=20?= =?UTF-8?q?of=20by-default=20hidden=20columns=20on=20high-DPI=20displays?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://winscp.net/tracker/2361 Source commit: 79a9e1d15ab353e30939b9a3f7ce561febcc94bc --- source/packages/my/ListViewColProperties.pas | 96 ++++++++++---------- source/packages/my/NortonLikeListView.pas | 1 + source/windows/VCLCommon.cpp | 10 +- 3 files changed, 54 insertions(+), 53 deletions(-) diff --git a/source/packages/my/ListViewColProperties.pas b/source/packages/my/ListViewColProperties.pas index f0bfb1883..ad43730a9 100644 --- a/source/packages/my/ListViewColProperties.pas +++ b/source/packages/my/ListViewColProperties.pas @@ -53,13 +53,13 @@ type procedure UpdateFromListView; procedure UpdateOrderFromListView; procedure UpdateListViewOrder; - procedure UpdateListViewMaxMinWidth; function GetProperties(Index: Integer): TCustomListViewColProperty; function GetIndexByOrder(Order: Integer): Integer; function ColumnsExists: Boolean; procedure SetRuntimeVisible(Index: Integer; Value: Boolean; SaveWidth: Boolean); function GetColumn(Index: Integer): TListColumn; procedure CreateProperties(ACount: Integer); + function DefaultConstraint(Value: Integer; Visible: Boolean; Def: Integer): Integer; property Columns: TListColumns read GetColumns stored False; public @@ -70,6 +70,7 @@ type procedure ListViewWndCreated; procedure ListViewWndDestroying; procedure ListViewWndDestroyed; + procedure ChangeScale(M, D: Integer); property Count: Integer read GetCount stored False; property Alignments[Index: Integer]: TAlignment read GetAlignments write SetAlignments; property Captions[Index: Integer]: string read GetCaptions write SetCaptions; @@ -568,12 +569,17 @@ begin end; end; +function TCustomListViewColProperties.DefaultConstraint(Value: Integer; Visible: Boolean; Def: Integer): Integer; +begin + if (Value > 0) and Visible then Result := Value + else Result := Def; +end; + procedure TCustomListViewColProperties.ListViewWndCreated; var Index: Integer; Properties: TCustomListViewColProperty; Column: TListColumn; - W: Integer; begin if FListViewManaged then begin @@ -587,36 +593,29 @@ begin UpdateListView; end; - if not FConstraintsInitialized then + Assert(ColumnsExists); + for Index := 0 to Count - 1 do begin - FConstraintsInitialized := True; + Column := GetColumn(Index); + Properties := GetProperties(Index); - for Index := 0 to Count - 1 do + if not FConstraintsInitialized then begin - Column := GetColumn(Index); - Properties := GetProperties(Index); + Properties.MaxWidth := DefaultConstraint(Column.MaxWidth, Properties.Visible, DefaultListViewMaxWidth); + Properties.MinWidth := DefaultConstraint(Column.MinWidth, Properties.Visible, DefaultListViewMinWidth); + end; - // Is this branching needed? - if Properties.Visible then - begin - W := Column.MaxWidth; - if W = 0 then W := DefaultListViewMaxWidth; - Properties.MaxWidth := ScaleByTextHeight(FListView, W); - - W := Column.MinWidth; - if W = 0 then W := DefaultListViewMinWidth; - Properties.MinWidth := ScaleByTextHeight(FListView, W); - end - else - begin - Column.MaxWidth := ScaleByTextHeight(FListView, Column.MaxWidth); - Column.MinWidth := ScaleByTextHeight(FListView, Column.MinWidth); - end; + // To apply the default constraints to columns that do not have their own + if Properties.Visible then + begin + Column.MaxWidth := Properties.MaxWidth; + if Column.Width > Column.MaxWidth then Column.Width := Column.MaxWidth; + Column.MinWidth := Properties.MinWidth; + if Column.Width < Column.MinWidth then Column.Width := Column.MinWidth; end; end; - // To apply the default constraints to columns that do not have their own - UpdateListViewMaxMinWidth; + FConstraintsInitialized := True; end; procedure TCustomListViewColProperties.ListViewWndDestroying; @@ -630,6 +629,30 @@ begin FCreated := False; end; +procedure TCustomListViewColProperties.ChangeScale(M, D: Integer); +var + Index: Integer; + Properties: TCustomListViewColProperty; + Column: TListColumn; +begin + for Index := 0 to Count - 1 do + begin + Properties := GetProperties(Index); + // This is not perfect, as the constraints apply on re-scaled width before they are re-scaled themselves + if Properties.Visible and ColumnsExists then + begin + Column := GetColumn(Index); + Column.MaxWidth := MulDiv(Column.MaxWidth, M, D); + Column.MinWidth := MulDiv(Column.MinWidth, M, D); + end + else + begin + Properties.MaxWidth := MulDiv(Properties.MaxWidth, M, D); + Properties.MinWidth := MulDiv(Properties.MinWidth, M, D); + end; + end; +end; + procedure TCustomListViewColProperties.UpdateListViewOrder; var Index: Integer; @@ -649,29 +672,6 @@ begin ListView_SetColumnOrderArray(FListView.Handle, Count, PInteger(Temp)); end; -procedure TCustomListViewColProperties.UpdateListViewMaxMinWidth; -var - Index: Integer; - Column: TListColumn; - Properties: TCustomListViewColProperty; -begin - Assert(ColumnsExists); - - for Index := 0 to Count-1 do - begin - Column := GetColumn(Index); - Properties := GetProperties(Index); - - if Properties.Visible then - begin - Column.MaxWidth := Properties.MaxWidth; - if Column.Width > Column.MaxWidth then Column.Width := Column.MaxWidth; - Column.MinWidth := Properties.MinWidth; - if Column.Width < Column.MinWidth then Column.Width := Column.MinWidth; - end; - end; -end; - procedure TCustomListViewColProperties.UpdateListView; var Index: Integer; diff --git a/source/packages/my/NortonLikeListView.pas b/source/packages/my/NortonLikeListView.pas index 5010bbf0f..9b8774e76 100644 --- a/source/packages/my/NortonLikeListView.pas +++ b/source/packages/my/NortonLikeListView.pas @@ -1131,6 +1131,7 @@ begin HandleNeeded; end; inherited; + ColProperties.ChangeScale(M, D); end; end. diff --git a/source/windows/VCLCommon.cpp b/source/windows/VCLCommon.cpp index 58da53403..d0609c43b 100644 --- a/source/windows/VCLCommon.cpp +++ b/source/windows/VCLCommon.cpp @@ -987,9 +987,9 @@ void __fastcall ApplySystemSettingsOnControl(TControl * Control) #endif TCustomListView * ListView = dynamic_cast(Control); - TCustomIEListView * IEListView = dynamic_cast(Control); - // For IEListView, this is (somewhat) handled in the TCustomListViewColProperties - if ((ListView != NULL) && (IEListView == NULL)) + TCustomNortonLikeListView * NortonLikeListView = dynamic_cast(Control); + // For NortonLikeListView, this is (somewhat) handled in the TCustomListViewColProperties + if ((ListView != NULL) && (NortonLikeListView == NULL)) { TListView * PublicListView = reinterpret_cast(ListView); @@ -1003,14 +1003,14 @@ void __fastcall ApplySystemSettingsOnControl(TControl * Control) // WORKAROUND for lack of public API for mimicking Explorer-style mouse selection // See https://stackoverflow.com/q/15750842/850848 - if (IEListView != NULL) + if (NortonLikeListView != NULL) { // It should not be a problem to call the LVM_QUERYINTERFACE // on earlier versions of Windows. It should be noop. if (IsWin7()) { IListView_Win7 * ListViewIntf = NULL; - SendMessage(IEListView->Handle, LVM_QUERYINTERFACE, reinterpret_cast(&IID_IListView_Win7), reinterpret_cast(&ListViewIntf)); + SendMessage(NortonLikeListView->Handle, LVM_QUERYINTERFACE, reinterpret_cast(&IID_IListView_Win7), reinterpret_cast(&ListViewIntf)); if (ListViewIntf != NULL) { ListViewIntf->SetSelectionFlags(1, 1);