浏览代码

Bug 1750: With every start on a monitor with different DPI than the primary monitor, dimensions of the window and some of its components change slightly

https://winscp.net/tracker/1750

Source commit: 57633915f3071aa337af7c305e987b0d2dc5d9c5
Martin Prikryl 6 年之前
父节点
当前提交
301be40a02
共有 3 个文件被更改,包括 72 次插入34 次删除
  1. 17 2
      source/forms/CustomScpExplorer.cpp
  2. 1 0
      source/forms/CustomScpExplorer.h
  3. 54 32
      source/windows/Tools.cpp

+ 17 - 2
source/forms/CustomScpExplorer.cpp

@@ -164,6 +164,7 @@ __fastcall TCustomScpExplorerForm::TCustomScpExplorerForm(TComponent* Owner):
   FCurrentSide = osRemote;
   FEverShown = false;
   FDocks = new TList();
+  InitControls();
   RestoreParams();
   ConfigurationChanged();
   RemoteDirView->Invalidate();
@@ -1238,7 +1239,7 @@ void __fastcall TCustomScpExplorerForm::RestoreFormParams()
 {
 }
 //---------------------------------------------------------------------------
-void __fastcall TCustomScpExplorerForm::RestoreParams()
+void __fastcall TCustomScpExplorerForm::InitControls()
 {
   DebugAssert(FDocks != NULL);
   for (int Index = 0; Index < ComponentCount; Index++)
@@ -1251,7 +1252,10 @@ void __fastcall TCustomScpExplorerForm::RestoreParams()
   }
 
   CollectItemsWithTextDisplayMode(this);
-
+}
+//---------------------------------------------------------------------------
+void __fastcall TCustomScpExplorerForm::RestoreParams()
+{
   ConfigurationChanged();
 
   QueuePanel->Height =
@@ -6829,6 +6833,17 @@ void __fastcall TCustomScpExplorerForm::DoShow()
   // only now are the controls resized finally, so the size constraints
   // will not conflict with possibly very small window size
   RestoreFormParams();
+  // This indicates that the form was rescaled after parameters were loaded and
+  // as most probably the parameters were actually saved with the current form scaling
+  // (windows was the last time likely closed on the same monitor, where it is starting now),
+  // rescaling happened twice already. Reload the parameters, as now they likely won't need any scaling
+  // and no rounding problems will occur.
+  // See also RestoreForm.
+  // (we should be safe to call RestoreParams unconditionally)
+  if (PixelsPerInch != Screen->PixelsPerInch)
+  {
+    RestoreParams();
+  }
 
   FixControlsPlacement();
 

+ 1 - 0
source/forms/CustomScpExplorer.h

@@ -325,6 +325,7 @@ private:
   void __fastcall DoBookmarkClick(TOperationSide Side, TObject * Sender);
   void __fastcall LocalBookmarkClick(TObject * Sender);
   void __fastcall RemoteBookmarkClick(TObject * Sender);
+  void __fastcall InitControls();
 
 protected:
   TOperationSide FCurrentSide;

+ 54 - 32
source/windows/Tools.cpp

@@ -181,6 +181,41 @@ void __fastcall LoadListViewStr(TListView * ListView, UnicodeString ALayoutStr)
   }
 }
 //---------------------------------------------------------------------------
+void __fastcall LoadFormDimensions(
+  const UnicodeString & LeftStr, const UnicodeString & TopStr, const UnicodeString & RightStr, const UnicodeString & BottomStr,
+  int PixelsPerInch, Forms::TMonitor * Monitor, TForm * Form, TRect & Bounds, bool & DefaultPos)
+{
+  int Left = StrToDimensionDef(LeftStr, PixelsPerInch, Form, Bounds.Left);
+  int Top = StrToDimensionDef(TopStr, PixelsPerInch, Form, Bounds.Top);
+  DefaultPos = (Left == -1) && (Top == -1);
+  if (!DefaultPos)
+  {
+    Bounds.Left = Left;
+    Bounds.Top = Top;
+  }
+  else
+  {
+    Bounds.Left = 0;
+    Bounds.Top = 0;
+  }
+  Bounds.Right = StrToDimensionDef(RightStr, PixelsPerInch, Form, Bounds.Right);
+  Bounds.Bottom = StrToDimensionDef(BottomStr, PixelsPerInch, Form, Bounds.Bottom);
+
+  // move to the target monitor
+  OffsetRect(Bounds, Monitor->Left, Monitor->Top);
+
+  // reduce window size to that of monitor size
+  // (this does not cut window into monitor!)
+  if (Bounds.Width() > Monitor->WorkareaRect.Width())
+  {
+    Bounds.Right -= (Bounds.Width() - Monitor->WorkareaRect.Width());
+  }
+  if (Bounds.Height() > Monitor->WorkareaRect.Height())
+  {
+    Bounds.Bottom -= (Bounds.Height() - Monitor->WorkareaRect.Height());
+  }
+}
+//---------------------------------------------------------------------------
 void __fastcall RestoreForm(UnicodeString Data, TForm * Form, bool PositionOnly)
 {
   DebugAssert(Form);
@@ -195,38 +230,14 @@ void __fastcall RestoreForm(UnicodeString Data, TForm * Form, bool PositionOnly)
     TWindowState State = (TWindowState)StrToIntDef(CutToChar(Data, L';', true), (int)wsNormal);
     int PixelsPerInch = LoadPixelsPerInch(CutToChar(Data, L';', true), Form);
 
-    TRect Bounds = Form->BoundsRect;
-    int Left = StrToDimensionDef(LeftStr, PixelsPerInch, Form, Bounds.Left);
-    int Top = StrToDimensionDef(TopStr, PixelsPerInch, Form, Bounds.Top);
-    bool DefaultPos = (Left == -1) && (Top == -1);
-    if (!DefaultPos)
-    {
-      Bounds.Left = Left;
-      Bounds.Top = Top;
-    }
-    else
-    {
-      Bounds.Left = 0;
-      Bounds.Top = 0;
-    }
-    Bounds.Right = StrToDimensionDef(RightStr, PixelsPerInch, Form, Bounds.Right);
-    Bounds.Bottom = StrToDimensionDef(BottomStr, PixelsPerInch, Form, Bounds.Bottom);
+    TRect OriginalBounds = Form->BoundsRect;
+    int OriginalPixelsPerInch = Form->PixelsPerInch;
     Form->WindowState = State;
     if (State == wsNormal)
     {
-      // move to the target monitor
-      OffsetRect(Bounds, Monitor->Left, Monitor->Top);
-
-      // reduce window size to that of monitor size
-      // (this does not cut window into monitor!)
-      if (Bounds.Width() > Monitor->WorkareaRect.Width())
-      {
-        Bounds.Right -= (Bounds.Width() - Monitor->WorkareaRect.Width());
-      }
-      if (Bounds.Height() > Monitor->WorkareaRect.Height())
-      {
-        Bounds.Bottom -= (Bounds.Height() - Monitor->WorkareaRect.Height());
-      }
+      bool DefaultPos;
+      TRect Bounds = OriginalBounds;
+      LoadFormDimensions(LeftStr, TopStr, RightStr, BottomStr, PixelsPerInch, Monitor, Form, Bounds, DefaultPos);
 
       if (DefaultPos ||
           ((Bounds.Left < Monitor->Left) ||
@@ -281,6 +292,17 @@ void __fastcall RestoreForm(UnicodeString Data, TForm * Form, bool PositionOnly)
         if (!PositionOnly)
         {
           Form->BoundsRect = Bounds;
+          // If setting bounds moved the form to another monitor with non-default DPI,
+          // recalculate the size to avoid rounding issues
+          // (as the form was very likely moved to the monitor, where the sizes were saved)
+          // See also TCustomScpExplorerForm::DoShow()
+          if (OriginalPixelsPerInch != Form->PixelsPerInch)
+          {
+            TRect Bounds2 = OriginalBounds;
+            LoadFormDimensions(LeftStr, TopStr, RightStr, BottomStr, PixelsPerInch, Monitor, Form, Bounds2, DefaultPos);
+            DebugAssert(!DefaultPos);
+            Form->BoundsRect = Bounds2;
+          }
         }
       }
     }
@@ -290,9 +312,9 @@ void __fastcall RestoreForm(UnicodeString Data, TForm * Form, bool PositionOnly)
 
       if (!PositionOnly)
       {
-        Bounds = Form->BoundsRect;
-        OffsetRect(Bounds, Monitor->Left, Monitor->Top);
-        Form->BoundsRect = Bounds;
+        TRect Bounds2 = Form->BoundsRect;
+        OffsetRect(Bounds2, Monitor->Left, Monitor->Top);
+        Form->BoundsRect = Bounds2;
       }
     }
   }