1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Issue 2361 – Layout problems of by-default hidden columns on high-DPI displays

https://winscp.net/tracker/2361

Source commit: 79a9e1d15ab353e30939b9a3f7ce561febcc94bc
This commit is contained in:
Martin Prikryl
2025-03-25 13:38:41 +00:00
parent f76012ddfb
commit 28ffba2df0
3 changed files with 54 additions and 53 deletions

View File

@@ -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;

View File

@@ -1131,6 +1131,7 @@ begin
HandleNeeded;
end;
inherited;
ColProperties.ChangeScale(M, D);
end;
end.

View File

@@ -987,9 +987,9 @@ void __fastcall ApplySystemSettingsOnControl(TControl * Control)
#endif
TCustomListView * ListView = dynamic_cast<TCustomListView *>(Control);
TCustomIEListView * IEListView = dynamic_cast<TCustomIEListView *>(Control);
// For IEListView, this is (somewhat) handled in the TCustomListViewColProperties
if ((ListView != NULL) && (IEListView == NULL))
TCustomNortonLikeListView * NortonLikeListView = dynamic_cast<TCustomNortonLikeListView *>(Control);
// For NortonLikeListView, this is (somewhat) handled in the TCustomListViewColProperties
if ((ListView != NULL) && (NortonLikeListView == NULL))
{
TListView * PublicListView = reinterpret_cast<TListView *>(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<WPARAM>(&IID_IListView_Win7), reinterpret_cast<LPARAM>(&ListViewIntf));
SendMessage(NortonLikeListView->Handle, LVM_QUERYINTERFACE, reinterpret_cast<WPARAM>(&IID_IListView_Win7), reinterpret_cast<LPARAM>(&ListViewIntf));
if (ListViewIntf != NULL)
{
ListViewIntf->SetSelectionFlags(1, 1);