diff --git a/src/System.Windows.Forms/PublicAPI.Unshipped.txt b/src/System.Windows.Forms/PublicAPI.Unshipped.txt index 3348c917404..904ff4f1046 100644 --- a/src/System.Windows.Forms/PublicAPI.Unshipped.txt +++ b/src/System.Windows.Forms/PublicAPI.Unshipped.txt @@ -1,3 +1,4 @@ +override System.Windows.Forms.Button.BackgroundImage.set -> void static System.Windows.Forms.Application.SetColorMode(System.Windows.Forms.SystemColorMode systemColorMode) -> void static System.Windows.Forms.TaskDialog.ShowDialogAsync(nint hwndOwner, System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation = System.Windows.Forms.TaskDialogStartupLocation.CenterOwner) -> System.Threading.Tasks.Task! static System.Windows.Forms.TaskDialog.ShowDialogAsync(System.Windows.Forms.IWin32Window! owner, System.Windows.Forms.TaskDialogPage! page, System.Windows.Forms.TaskDialogStartupLocation startupLocation = System.Windows.Forms.TaskDialogStartupLocation.CenterOwner) -> System.Threading.Tasks.Task! diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/Button.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/Button.cs index e76dd755f29..6eada6bc3d9 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/Button.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/Button.cs @@ -148,6 +148,21 @@ public virtual DialogResult DialogResult } } + public override Image? BackgroundImage + { + set + { + base.BackgroundImage = value; + + if (Application.IsDarkModeEnabled) + { + // BackgroundImage changes may affect rendering logic, + // so we manually update the OwnerDraw flag to ensure correct visual behavior. + UpdateOwnerDraw(); + } + } + } + /// /// Defines, whether the control is owner-drawn. Based on this, /// the UserPaint flags get set, which in turn makes it later @@ -161,7 +176,6 @@ private protected override bool OwnerDraw get { if (Application.IsDarkModeEnabled - // The SystemRenderer cannot render images. So, we flip to our // own DarkMode renderer, if we need to render images, except if... && Image is null diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/ButtonBaseAdapter.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/ButtonBaseAdapter.cs index 39b5b0ab852..9e97f45b584 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/ButtonBaseAdapter.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/ButtonBaseAdapter.cs @@ -547,21 +547,6 @@ internal void PaintField( /// internal void PaintImage(PaintEventArgs e, LayoutData layout) { - if (Application.IsDarkModeEnabled && Control.DarkModeRequestState is true && Control.BackgroundImage is not null) - { - Rectangle bounds = Control.ClientRectangle; - bounds.Inflate(-ButtonBorderSize, -ButtonBorderSize); - ControlPaint.DrawBackgroundImage( - e.GraphicsInternal, - Control.BackgroundImage, - Color.Transparent, - Control.BackgroundImageLayout, - Control.ClientRectangle, - bounds, - Control.DisplayRectangle.Location, - Control.RightToLeft); - } - if (Control.Image is not null) { // Setup new clip region & draw diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs index a85dd3ed4cc..34458e21981 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs @@ -70,6 +70,32 @@ private Color GetButtonBackColor(PushButtonState state) return backColor; } + internal void PaintBackgroundImage(PaintEventArgs e, int borderSize, Rectangle paddedBounds) + { + if (Control.BackgroundImage is not null) + { + Rectangle bounds = paddedBounds; + if (Control.FlatStyle == FlatStyle.Flat) + { + bounds.Inflate(-borderSize - 1, -borderSize - 1); + } + else + { + bounds.Inflate(-1, -1); + } + + ControlPaint.DrawBackgroundImage( + e.GraphicsInternal, + Control.BackgroundImage, + Color.Transparent, + Control.BackgroundImageLayout, + paddedBounds, + bounds, + bounds.Location, + Control.RightToLeft); + } + } + internal override void PaintUp(PaintEventArgs e, CheckState state) { try @@ -93,6 +119,10 @@ internal override void PaintUp(PaintEventArgs e, CheckState state) Control.Parent?.BackColor ?? Control.BackColor, GetButtonBackColor(pushButtonState), _ => PaintImage(e, layout), + _ => PaintBackgroundImage( + e, + Control.FlatAppearance.BorderSize, + Control.ClientRectangle), () => PaintField( e, layout, @@ -131,6 +161,10 @@ internal override void PaintDown(PaintEventArgs e, CheckState state) Control.Parent?.BackColor ?? Control.BackColor, GetButtonBackColor(PushButtonState.Pressed), _ => PaintImage(e, layout), + _ => PaintBackgroundImage( + e, + Control.FlatAppearance.BorderSize, + Control.ClientRectangle), () => PaintField( e, layout, @@ -169,6 +203,10 @@ internal override void PaintOver(PaintEventArgs e, CheckState state) Control.Parent?.BackColor ?? Control.BackColor, GetButtonBackColor(PushButtonState.Hot), _ => PaintImage(e, layout), + _ => PaintBackgroundImage( + e, + Control.FlatAppearance.BorderSize, + Control.ClientRectangle), () => PaintField( e, layout, diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeRendererBase.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeRendererBase.cs index 9d655a618b0..55897ec79d7 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeRendererBase.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeRendererBase.cs @@ -39,6 +39,7 @@ public void RenderButton( Color parentBackgroundColor, Color backColor, Action paintImage, + Action paintBackgroundImage, Action paintField) { ArgumentNullException.ThrowIfNull(graphics); @@ -63,6 +64,8 @@ public void RenderButton( // Draw button background and get content bounds Rectangle contentBounds = DrawButtonBackground(graphics, paddedBounds, state, isDefault, backColor); + paintBackgroundImage(paddedBounds); + // Paint image and field using the provided delegates paintImage(contentBounds); diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/IButtonRenderer.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/IButtonRenderer.cs index ab1f7844042..5490b7c069f 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/IButtonRenderer.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/IButtonRenderer.cs @@ -50,6 +50,7 @@ void RenderButton( Color parentBackgroundColor, Color backColor, Action paintImage, + Action paintBackgroundImage, Action paintField); ///