Bläddra i källkod

Dark theme for message boxes (part of Issue 1696)

https://winscp.net/tracker/1696

Source commit: 8922ca214bc7cb6b7f7accf19ec946763681650a
Martin Prikryl 5 månader sedan
förälder
incheckning
907f2ecf4c

+ 1 - 1
source/forms/Authenticate.cpp

@@ -209,7 +209,7 @@ void __fastcall TAuthenticateForm::AdjustControls()
 //---------------------------------------------------------------------------
 TLabel * __fastcall TAuthenticateForm::GenerateLabel(int Current, UnicodeString Caption)
 {
-  TLabel * Result = new TUIStateAwareLabel(this);
+  TLabel * Result = CreateLabel(this);
   Result->Parent = FPromptParent;
 
   Result->Anchors = TAnchors() << akLeft << akTop << akRight;

+ 1 - 1
source/forms/Custom.cpp

@@ -179,7 +179,7 @@ TCheckBox * __fastcall TCustomDialog::CreateAndAddCheckBox(const UnicodeString &
 //---------------------------------------------------------------------------
 TLabel * __fastcall TCustomDialog::CreateLabel(UnicodeString Label)
 {
-  TLabel * Result = new TUIStateAwareLabel(this);
+  TLabel * Result = ::CreateLabel(this);
   Result->Caption = Label;
   return Result;
 }

+ 1 - 1
source/forms/CustomScpExplorer.cpp

@@ -1057,7 +1057,7 @@ void TCustomScpExplorerForm::CheckStoreTransition()
     Toolbar->Items->Add(LabelItem);
 
     TTBXCustomItem * LinkItem = new TTBXItem(Toolbar);
-    LinkItem->FontSettings->Color = LinkColor;
+    LinkItem->FontSettings->Color = GetLightLinkColor(); // the background is not themed yet
     LinkItem->Caption = LoadStr(STORE_MIGRATION_LEARN);
     LinkItem->OnClick = StoreTransitionLinkClick;
     Toolbar->Items->Add(LinkItem);

+ 1 - 1
source/forms/EditorPreferences.cpp

@@ -79,7 +79,7 @@ void __fastcall TEditorPreferencesDialog::Init(TEditorPreferencesMode Mode, bool
     ExternalEditorBrowseButton->Top = ExternalEditorBrowseButton->Top - Shift;
     Shift += (EditorExternalButton->Top - EditorInternalButton->Top);
     EditorGroup2->Height = EditorGroup2->Height - Shift;
-    TLabel * ExternalEditorLabel = new TUIStateAwareLabel(this);
+    TLabel * ExternalEditorLabel = CreateLabel(this);
     ExternalEditorLabel->Caption = EditorExternalButton->Caption;
     ExternalEditorLabel->Parent = EditorGroup2;
     ExternalEditorLabel->Top = MaskLabel->Top;

+ 35 - 8
source/forms/MessageDlg.cpp

@@ -382,6 +382,12 @@ void __fastcall TMessageForm::CreateParams(TCreateParams & Params)
   }
 }
 //---------------------------------------------------------------------------
+void __fastcall TMessageForm::CreateWnd()
+{
+  TForm::CreateWnd();
+  ApplyColorMode(this);
+}
+//---------------------------------------------------------------------------
 void __fastcall TMessageForm::LoadMessageBrowser()
 {
   NavigateToUrl(MessageBrowserUrl);
@@ -623,12 +629,17 @@ TButton * __fastcall TMessageForm::CreateButton(
   return Button;
 }
 //---------------------------------------------------------------------------
+TControl * TMessageForm::GetContentsControls()
+{
+  return static_cast<TControl *>(DebugNotNull(MessageBrowser))->Parent;
+}
+//---------------------------------------------------------------------------
 void __fastcall TMessageForm::InsertPanel(TPanel * Panel)
 {
   if (DebugAlwaysTrue(MessageBrowser != NULL))
   {
     // we currently use this for updates message box only
-    TControl * ContentsControl = static_cast<TControl *>(DebugNotNull(MessageBrowser))->Parent;
+    TControl * ContentsControl = GetContentsControls();
 
     Panel->Parent = ContentsPanel;
     Panel->Width = ContentsControl->Width;
@@ -650,8 +661,18 @@ int __fastcall TMessageForm::GetContentWidth()
   if (DebugAlwaysTrue(MessageBrowser != NULL))
   {
     // we currently use this for updates message box only
-    TControl * ContentsControl = static_cast<TControl *>(DebugNotNull(MessageBrowser))->Parent;
-    Result = ContentsControl->Width;
+    Result = GetContentsControls()->Width;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+static UnicodeString UrlColor(TColor Color)
+{
+  UnicodeString Result = ColorToWebColorStr(Color);
+  DebugAssert(Result.Length() == 7);
+  if (DebugAlwaysTrue(StartsStr(L"#", Result)))
+  {
+    Result.Delete(1, 1);
   }
   return Result;
 }
@@ -660,8 +681,9 @@ void __fastcall TMessageForm::NavigateToUrl(const UnicodeString & Url)
 {
   if (DebugAlwaysTrue(MessageBrowser != NULL))
   {
-    UnicodeString FontSizeParam = FORMAT(L"fontsize=%d", (Font->Size));
-    UnicodeString FullUrl = AppendUrlParams(Url, FontSizeParam);
+    UnicodeString StyleParams =
+      FORMAT(L"fontsize=%d&textcolor=%s&backcolor=%s", (Font->Size, UrlColor(Font->Color), UrlColor(GetControlColor(GetContentsControls()))));
+    UnicodeString FullUrl = AppendUrlParams(Url, StyleParams);
     NavigateBrowserToUrl(MessageBrowser, FullUrl);
   }
 }
@@ -780,12 +802,18 @@ TForm * __fastcall TMessageForm::Create(const UnicodeString & Msg,
     *TimeoutButton = NULL;
   }
 
+  TMessageForm * Result = SafeFormCreate<TMessageForm>();
+
   TColor MainInstructionColor;
   HFONT MainInstructionFont;
   HFONT InstructionFont;
   GetInstrutionsTheme(MainInstructionColor, MainInstructionFont, InstructionFont);
 
-  TMessageForm * Result = SafeFormCreate<TMessageForm>();
+  if (UseDarkModeForControl(Result))
+  {
+    MainInstructionColor = GetLinkColor(Result);
+  }
+
   if (InstructionFont != 0)
   {
     Result->Font->Handle = InstructionFont;
@@ -951,7 +979,6 @@ TForm * __fastcall TMessageForm::Create(const UnicodeString & Msg,
   Result->ContentsPanel = Panel;
   Panel->Name = MessagePanelName;
   Panel->Parent = Result;
-  Panel->Color = clWindow;
   Panel->ParentBackground = false;
   Panel->Anchors = TAnchors() << akLeft << akRight << akTop;
   Panel->Caption = L"";
@@ -1197,7 +1224,7 @@ TForm * __fastcall TMessageForm::Create(const UnicodeString & Msg,
   if (!NeverAskAgainCaption.IsEmpty() &&
       !ButtonControls.empty())
   {
-    Result->NeverAskAgainCheck = new TCheckBox(Result);
+    Result->NeverAskAgainCheck = CreateCheckBox(Result);
     Result->NeverAskAgainCheck->Name = L"NeverAskAgainCheck";
     Result->NeverAskAgainCheck->Parent = Result;
     Result->NeverAskAgainCheck->Caption = NeverAskAgainCaption;

+ 2 - 0
source/forms/MessageDlg.h

@@ -34,6 +34,7 @@ protected:
   UnicodeString __fastcall GetReportText();
   UnicodeString __fastcall NormalizeNewLines(UnicodeString Text);
   virtual void __fastcall CreateParams(TCreateParams & Params);
+  virtual void __fastcall CreateWnd();
   DYNAMIC void __fastcall DoShow();
   virtual void __fastcall Dispatch(void * Message);
   void __fastcall MenuItemClick(TObject * Sender);
@@ -42,6 +43,7 @@ protected:
   void __fastcall UpdateForShiftStateTimer(TObject * Sender);
   DYNAMIC void __fastcall SetZOrder(bool TopMost);
   void __fastcall LoadMessageBrowser();
+  TControl * GetContentsControls();
 
 private:
   typedef std::map<unsigned int, TButton *> TAnswerButtons;

+ 51 - 14
source/windows/GUITools.cpp

@@ -1533,15 +1533,6 @@ void __fastcall TBrowserViewer::NavigateToUrl(const UnicodeString & Url)
   Navigate(Url.c_str());
 }
 //---------------------------------------------------------------------------
-TPanel * __fastcall CreateLabelPanel(TPanel * Parent, const UnicodeString & Label)
-{
-  TPanel * Result = CreateBlankPanel(Parent);
-  Result->Parent = Parent;
-  Result->Align = alClient;
-  Result->Caption = Label;
-  return Result;
-}
-//---------------------------------------------------------------------------
 TWebBrowserEx * __fastcall CreateBrowserViewer(TPanel * Parent, const UnicodeString & LoadingLabel)
 {
   TBrowserViewer * Result = new TBrowserViewer(Parent);
@@ -1621,6 +1612,25 @@ bool CopyTextFromBrowser(TWebBrowserEx * WebBrowser, UnicodeString & Text)
   return Result;
 }
 //---------------------------------------------------------------------------
+TPanel * CreateBlankPanel(TComponent * Owner)
+{
+  TPanel * Panel = new TPanel(Owner);
+  Panel->BevelOuter = bvNone;
+  Panel->BevelInner = bvNone; // default
+  Panel->BevelKind = bkNone;
+  Panel->Color = clWindow;
+  return Panel;
+}
+//---------------------------------------------------------------------------
+TPanel * CreateLabelPanel(TPanel * Parent, const UnicodeString & Label)
+{
+  TPanel * Result = CreateBlankPanel(Parent);
+  Result->Parent = Parent;
+  Result->Align = alClient;
+  Result->Caption = Label;
+  return Result;
+}
+//---------------------------------------------------------------------------
 UnicodeString GenerateAppHtmlPage(TFont * Font, TPanel * Parent, const UnicodeString & Body, bool Seamless)
 {
   UnicodeString Result =
@@ -1634,12 +1644,9 @@ UnicodeString GenerateAppHtmlPage(TFont * Font, TPanel * Parent, const UnicodeSt
     L"{\n"
     L"    font-family: '" + Font->Name + L"';\n"
     L"    margin: " + UnicodeString(Seamless ? L"0" : L"0.5em") + L";\n"
+    L"    color: " + ColorToWebColorStr(Parent->Font->Color) + L";\n"
     L"    background-color: " + ColorToWebColorStr(Parent->Color) + L";\n" +
     UnicodeString(Seamless ? L"    overflow: hidden;\n" : L"") +
-    L"}\n"
-    L"\n"
-    L"body\n"
-    L"{\n"
     L"    font-size: " + IntToStr(Font->Size) + L"pt;\n"
     L"}\n"
     L"\n"
@@ -1651,7 +1658,7 @@ UnicodeString GenerateAppHtmlPage(TFont * Font, TPanel * Parent, const UnicodeSt
     L"\n"
     L"a, a:visited, a:hover, a:visited, a:current\n"
     L"{\n"
-    L"    color: " + ColorToWebColorStr(LinkColor) + L";\n"
+    L"    color: " + ColorToWebColorStr(GetLinkColor(Parent)) + L";\n"
     L"}\n"
     L"</style>\n"
     L"</head>\n"
@@ -2456,6 +2463,24 @@ bool __fastcall TDarkUxThemeStyle::DoDrawText(
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
+// Based on:
+// https://stackoverflow.com/q/6912424/850848
+// https://stackoverflow.com/q/4685863/850848
+class TUIStateAwareLabel : public TLabel
+{
+public:
+  __fastcall virtual TUIStateAwareLabel(TComponent * AOwner);
+
+protected:
+  DYNAMIC void __fastcall DoDrawText(TRect & Rect, int Flags);
+  virtual void __fastcall Dispatch(void * AMessage);
+};
+//---------------------------------------------------------------------------
+TLabel * CreateLabel(TComponent * AOwner)
+{
+  return new TUIStateAwareLabel(AOwner);
+}
+//---------------------------------------------------------------------------
 __fastcall TUIStateAwareLabel::TUIStateAwareLabel(TComponent * AOwner) :
   TLabel(AOwner)
 {
@@ -2577,12 +2602,19 @@ protected:
 //---------------------------------------------------------------------------
 class TCheckBoxEx : public TCheckBox
 {
+public:
+  __fastcall virtual TCheckBoxEx(TComponent * AOwner);
 protected:
   virtual void __fastcall WndProc(TMessage & Msg);
 private:
   std::unique_ptr<TDarkCheckBoxStyleHook> FStyleHook;
 };
 //---------------------------------------------------------------------------
+TCheckBox * CreateCheckBox(TComponent * AOwner)
+{
+  return new TCheckBoxEx(AOwner);
+}
+//---------------------------------------------------------------------------
 __fastcall TDarkCheckBoxStyleHook::TDarkCheckBoxStyleHook(TWinControl * AControl) :
   TCheckBoxStyleHook(AControl)
 {
@@ -2600,6 +2632,11 @@ TCustomStyleServices * __fastcall TDarkCheckBoxStyleHook::StyleServices()
   return TDarkUxThemeStyle::Instance();
 }
 //---------------------------------------------------------------------------
+__fastcall TCheckBoxEx::TCheckBoxEx(TComponent * AOwner) :
+  TCheckBox(AOwner)
+{
+}
+//---------------------------------------------------------------------------
 void __fastcall TCheckBoxEx::WndProc(TMessage & Msg)
 {
   if (!HandleMessageByDarkStyleHook(Msg, this, FStyleHook))

+ 4 - 13
source/windows/GUITools.h

@@ -37,7 +37,10 @@ typedef int __fastcall (*TCalculateWidth)(UnicodeString Text, void * Arg);
 void __fastcall ApplyTabs(
   UnicodeString & Text, wchar_t Padding,
   TCalculateWidth CalculateWidth, void * CalculateWidthArg);
-TPanel * __fastcall CreateLabelPanel(TPanel * Parent, const UnicodeString & Label);
+TPanel * CreateBlankPanel(TComponent * Owner);
+TPanel * CreateLabelPanel(TPanel * Parent, const UnicodeString & Label);
+TLabel * CreateLabel(TComponent * AOwner);
+TCheckBox * CreateCheckBox(TComponent * AOwner);
 void __fastcall SelectScaledImageList(TImageList * ImageList);
 void __fastcall CopyImageList(TImageList * TargetList, TImageList * SourceList);
 void __fastcall LoadDialogImage(TImage * Image, const UnicodeString & ImageName);
@@ -178,18 +181,6 @@ private:
     TControl * HintControl, const UnicodeString & Hint, UnicodeString & ShortHint, UnicodeString & LongHint);
 };
 //---------------------------------------------------------------------------
-// Based on:
-// https://stackoverflow.com/q/6912424/850848
-// https://stackoverflow.com/q/4685863/850848
-class TUIStateAwareLabel : public TLabel
-{
-public:
-  __fastcall virtual TUIStateAwareLabel(TComponent * AOwner);
-
-protected:
-  DYNAMIC void __fastcall DoDrawText(TRect & Rect, int Flags);
-  virtual void __fastcall Dispatch(void * AMessage);
-};
 // FindComponentClass takes parameter by reference and as such it cannot be implemented in
 // an inline method without a compiler warning, which we cannot suppress in a macro.
 // And having the implementation in a real code (not macro) also allows us to debug the code.

+ 11 - 0
source/windows/Tools.cpp

@@ -132,6 +132,17 @@ TColor __fastcall GetBtnFaceColor()
   return WinConfiguration->UseDarkTheme() ? TColor(RGB(43, 43, 43)) : clBtnFace;
 }
 //---------------------------------------------------------------------------
+TColor GetLightLinkColor()
+{
+  return clBlue;
+}
+//---------------------------------------------------------------------------
+TColor GetLinkColor(TControl * Control)
+{
+  // dark theme Windows 11 Settings app On/Off toggle color
+  return UseDarkModeForControl(Control) ? TColor(RGB(0x4C, 0xC2, 0xFF)) : GetLightLinkColor();
+}
+//---------------------------------------------------------------------------
 TColor __fastcall GetNonZeroColor(TColor Color)
 {
   // 0,0,0 is "default color"

+ 2 - 0
source/windows/Tools.h

@@ -39,6 +39,8 @@ bool __fastcall SameFont(TFont * Font1, TFont * Font2);
 TColor __fastcall GetWindowTextColor(TColor BackgroundColor, TColor Color = static_cast<TColor>(0));
 TColor __fastcall GetWindowColor(TColor Color = static_cast<TColor>(0));
 TColor __fastcall GetBtnFaceColor();
+TColor GetLightLinkColor();
+TColor GetLinkColor(TControl * Control);
 TColor __fastcall GetNonZeroColor(TColor Color);
 void ValidateMask(const UnicodeString & Mask, int ForceDirectoryMasks = -1);
 void __fastcall ValidateMaskEdit(TComboBox * Edit);

+ 19 - 15
source/windows/VCLCommon.cpp

@@ -531,6 +531,7 @@ class TPublicControl : public TControl
 friend void __fastcall RealignControl(TControl * Control);
 friend TCanvas * CreateControlCanvas(TControl * Control);
 friend void ApplyDarkModeOnControl(TControl * Control);
+friend TColor GetControlColor(TControl * Control);
 };
 //---------------------------------------------------------------------
 class TPublicForm : public TForm
@@ -1089,11 +1090,17 @@ void __fastcall ResetSystemSettings(TForm * /*Control*/)
   // noop
 }
 //---------------------------------------------------------------------------
+TColor GetControlColor(TControl * Control)
+{
+  return static_cast<TPublicControl *>(Control)->Color;
+}
+//---------------------------------------------------------------------------
 void ApplyDarkModeOnControl(TControl * Control)
 {
   TPublicControl * PublicControl = static_cast<TPublicControl *>(Control);
 
   TColor BtnFaceColor = GetBtnFaceColor();
+  TColor WindowColor = GetWindowColor();
   if (dynamic_cast<TForm *>(Control) != NULL)
   {
     DebugAssert((PublicControl->Color == clBtnFace) || (PublicControl->Color == BtnFaceColor));
@@ -1103,14 +1110,20 @@ void ApplyDarkModeOnControl(TControl * Control)
 
   if (dynamic_cast<TPanel *>(Control) != NULL)
   {
-    DebugAssert((PublicControl->Color == clBtnFace) || (PublicControl->Color == BtnFaceColor));
     DebugAssert(!PublicControl->ParentColor);
-    PublicControl->Color = BtnFaceColor;
+    if ((PublicControl->Color == clWindow) || (PublicControl->Color == WindowColor))
+    {
+      PublicControl->Color = WindowColor;
+    }
+    else
+    {
+      DebugAssert((PublicControl->Color == clBtnFace) || (PublicControl->Color == BtnFaceColor));
+      PublicControl->Color = BtnFaceColor;
+    }
   }
 
   if (IsWindowColorControl(Control))
   {
-    TColor WindowColor = GetWindowColor();
     DebugAssert((PublicControl->Color == clWindow) || (PublicControl->Color == WindowColor));
     DebugAssert(!PublicControl->ParentColor);
     PublicControl->Color = WindowColor;
@@ -1990,7 +2003,7 @@ static void __fastcall FocusableLabelWindowProc(void * Data, TMessage & Message,
       {
         Canvas->DrawFocusRect(R);
       }
-      else if ((StaticText->Font->Color != LinkColor) && // LinkActionLabel and LinkLabel
+      else if ((StaticText->Font->Color != GetLinkColor(StaticText)) && // LinkActionLabel and LinkLabel
                !EndsStr(LinkAppLabelMark, StaticText->Caption)) // LinkAppLabel
       {
         Canvas->Pen->Style = psDot;
@@ -2338,7 +2351,7 @@ void __fastcall LinkLabel(TStaticText * StaticText, UnicodeString Url,
     }
   }
 
-  StaticText->Font->Color = LinkColor;
+  StaticText->Font->Color = GetLinkColor(StaticText);
 }
 //---------------------------------------------------------------------------
 void __fastcall LinkActionLabel(TStaticText * StaticText)
@@ -2347,7 +2360,7 @@ void __fastcall LinkActionLabel(TStaticText * StaticText)
   DebugAssert(StaticText->Parent != NULL);
   DoLinkLabel(StaticText);
 
-  StaticText->Font->Color = LinkColor;
+  StaticText->Font->Color = GetLinkColor(StaticText);
 }
 //---------------------------------------------------------------------------
 void __fastcall LinkAppLabel(TStaticText * StaticText)
@@ -2831,15 +2844,6 @@ void __fastcall ShowFormNoActivate(TForm * Form)
   }
 }
 //---------------------------------------------------------------------------
-TPanel * __fastcall CreateBlankPanel(TComponent * Owner)
-{
-  TPanel * Panel = new TPanel(Owner);
-  Panel->BevelOuter = bvNone;
-  Panel->BevelInner = bvNone; // default
-  Panel->BevelKind = bkNone;
-  return Panel;
-}
-//---------------------------------------------------------------------------
 bool IsButtonBeingClicked(TButtonControl * Button)
 {
   class TPublicButtonControl : public TButtonControl

+ 1 - 2
source/windows/VCLCommon.h

@@ -8,7 +8,6 @@
 #include <ComCtrls.hpp>
 #include <HistoryComboBox.hpp>
 //---------------------------------------------------------------------------
-const TColor LinkColor = clBlue;
 extern const UnicodeString ContextSeparator;
 //---------------------------------------------------------------------------
 void __fastcall FixListColumnWidth(TListView * TListView, int Index);
@@ -26,6 +25,7 @@ void __fastcall UseSystemSettingsPre(TForm * Control);
 void __fastcall UseSystemSettingsPost(TForm * Control);
 void __fastcall UseSystemSettings(TForm * Control);
 void __fastcall ResetSystemSettings(TForm * Control);
+TColor GetControlColor(TControl * Control);
 void UseDarkMode(TForm * Form);
 void ApplyColorMode(TForm * Form);
 void __fastcall LinkLabel(TStaticText * StaticText, UnicodeString Url = L"",
@@ -88,7 +88,6 @@ void __fastcall RealignControl(TControl * Control);
 void __fastcall HookFormActivation(TCustomForm * Form);
 void __fastcall UnhookFormActivation(TCustomForm * Form);
 void __fastcall ShowFormNoActivate(TForm * Form);
-TPanel * __fastcall CreateBlankPanel(TComponent * Owner);
 typedef void __fastcall (*TRescaleEvent)(TComponent * Sender, TObject * Token);
 void __fastcall SetRescaleFunction(
   TComponent * Component, TRescaleEvent OnRescale, TObject * Token = NULL, bool OwnsToken = false);