Skip to content

Commit 7740992

Browse files
Leaf ShiLeaf Shi
authored andcommitted
Fix the border issue
1 parent 9e82a5f commit 7740992

File tree

7 files changed

+69
-32
lines changed

7 files changed

+69
-32
lines changed

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/ButtonBaseAdapter.cs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -547,19 +547,6 @@ internal void PaintField(
547547
/// </summary>
548548
internal void PaintImage(PaintEventArgs e, LayoutData layout)
549549
{
550-
if (Application.IsDarkModeEnabled && Control.DarkModeRequestState is true && Control.BackgroundImage is not null)
551-
{
552-
ControlPaint.DrawBackgroundImage(
553-
e.GraphicsInternal,
554-
Control.BackgroundImage,
555-
Color.Transparent,
556-
Control.BackgroundImageLayout,
557-
Control.ClientRectangle,
558-
Control.ClientRectangle,
559-
Control.DisplayRectangle.Location,
560-
Control.RightToLeft);
561-
}
562-
563550
if (Control.Image is not null)
564551
{
565552
// Setup new clip region & draw

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,32 @@ private Color GetButtonBackColor(PushButtonState state)
7070
return textColor;
7171
}
7272

73+
internal void PaintBackgroundImage(PaintEventArgs e, int borderSize, Rectangle paddedBounds)
74+
{
75+
if (Application.IsDarkModeEnabled && Control.DarkModeRequestState is true && Control.BackgroundImage is not null)
76+
{
77+
Rectangle bounds = paddedBounds;
78+
if (Control.FlatStyle == FlatStyle.Popup)
79+
{
80+
bounds.Inflate(-1, -1);
81+
}
82+
else
83+
{
84+
bounds.Inflate(-1 - borderSize, -1 - borderSize);
85+
}
86+
87+
ControlPaint.DrawBackgroundImage(
88+
e.GraphicsInternal,
89+
Control.BackgroundImage,
90+
Color.Transparent,
91+
Control.BackgroundImageLayout,
92+
paddedBounds,
93+
bounds,
94+
bounds.Location,
95+
Control.RightToLeft);
96+
}
97+
}
98+
7399
internal override void PaintUp(PaintEventArgs e, CheckState state)
74100
{
75101
try
@@ -86,13 +112,18 @@ internal override void PaintUp(PaintEventArgs e, CheckState state)
86112
g,
87113
Control.ClientRectangle,
88114
Control.FlatStyle,
115+
Control.FlatAppearance.BorderSize,
89116
pushButtonState,
90117
Control.IsDefault,
91118
Control.Focused,
92119
Control.ShowFocusCues,
93120
Control.Parent?.BackColor ?? Control.BackColor,
94121
GetButtonBackColor(pushButtonState),
95122
_ => PaintImage(e, layout),
123+
_ => PaintBackgroundImage(
124+
e,
125+
Control.FlatAppearance.BorderSize,
126+
Control.ClientRectangle),
96127
() => PaintField(
97128
e,
98129
layout,
@@ -124,13 +155,18 @@ internal override void PaintDown(PaintEventArgs e, CheckState state)
124155
g,
125156
Control.ClientRectangle,
126157
Control.FlatStyle,
158+
Control.FlatAppearance.BorderSize,
127159
PushButtonState.Pressed,
128160
Control.IsDefault,
129161
Control.Focused,
130162
Control.ShowFocusCues,
131163
Control.Parent?.BackColor ?? Control.BackColor,
132164
GetButtonBackColor(PushButtonState.Pressed),
133165
_ => PaintImage(e, layout),
166+
_ => PaintBackgroundImage(
167+
e,
168+
Control.FlatAppearance.BorderSize,
169+
Control.ClientRectangle),
134170
() => PaintField(
135171
e,
136172
layout,
@@ -156,19 +192,23 @@ internal override void PaintOver(PaintEventArgs e, CheckState state)
156192
var g = e.GraphicsInternal;
157193
var smoothingMode = g.SmoothingMode;
158194
g.SmoothingMode = Drawing.Drawing2D.SmoothingMode.AntiAlias;
159-
160195
LayoutData layout = CommonLayout().Layout();
161196
ButtonDarkModeRenderer.RenderButton(
162197
g,
163198
Control.ClientRectangle,
164199
Control.FlatStyle,
200+
Control.FlatAppearance.BorderSize,
165201
PushButtonState.Hot,
166202
Control.IsDefault,
167203
Control.Focused,
168204
Control.ShowFocusCues,
169205
Control.Parent?.BackColor ?? Control.BackColor,
170206
GetButtonBackColor(PushButtonState.Hot),
171207
_ => PaintImage(e, layout),
208+
_ => PaintBackgroundImage(
209+
e,
210+
Control.FlatAppearance.BorderSize,
211+
Control.ClientRectangle),
172212
() => PaintField(
173213
e,
174214
layout,

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeRendererBase.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ public void RenderButton(
3232
Graphics graphics,
3333
Rectangle bounds,
3434
FlatStyle flatStyle,
35+
int borderSize,
3536
PushButtonState state,
3637
bool isDefault,
3738
bool focused,
3839
bool showFocusCues,
3940
Color parentBackgroundColor,
4041
Color backColor,
4142
Action<Rectangle> paintImage,
43+
Action<Rectangle> paintBackgroundImage,
4244
Action paintField)
4345
{
4446
ArgumentNullException.ThrowIfNull(graphics);
@@ -61,12 +63,14 @@ public void RenderButton(
6163
height: bounds.Height - padding.Vertical);
6264

6365
// Draw button background and get content bounds
64-
Rectangle contentBounds = DrawButtonBackground(graphics, paddedBounds, state, isDefault, backColor);
66+
Rectangle contentBounds = DrawButtonBackground(graphics, paddedBounds, borderSize, state, isDefault, backColor);
67+
68+
paintBackgroundImage(paddedBounds);
6569

6670
// Paint image and field using the provided delegates
6771
paintImage(contentBounds);
6872

69-
DrawButtonBorder(graphics, bounds, state, isDefault);
73+
DrawButtonBorder(graphics, bounds, borderSize, state, isDefault);
7074

7175
paintField();
7276

@@ -78,9 +82,9 @@ public void RenderButton(
7882
}
7983
}
8084

81-
public abstract void DrawButtonBorder(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault);
85+
public abstract void DrawButtonBorder(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault);
8286

83-
public abstract Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault, Color backColor);
87+
public abstract Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault, Color backColor);
8488

8589
public abstract void DrawFocusIndicator(Graphics graphics, Rectangle contentBounds, bool isDefault);
8690

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/FlatButtonDarkModeRenderer.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ internal sealed class FlatButtonDarkModeRenderer : ButtonDarkModeRendererBase
2121
private protected override Padding PaddingCore { get; } = new(0);
2222

2323
public override Rectangle DrawButtonBackground(
24-
Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault, Color backColor)
24+
Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault, Color backColor)
2525
{
2626
// fill background
2727
using var back = backColor.GetCachedSolidBrushScope();
28-
graphics.FillRectangle(back, bounds);
28+
29+
Rectangle rectangle = bounds;
30+
rectangle.Inflate(-1 - borderSize, -1 - borderSize);
31+
32+
graphics.FillRectangle(back, rectangle);
2933
// return inner content area (border + 1 px system padding)
3034
return Rectangle.Inflate(bounds, -3, -3);
3135
}
@@ -71,29 +75,28 @@ public override Color GetBackgroundColor(PushButtonState state, bool isDefault)
7175
_ => DefaultColors.StandardBackColor
7276
};
7377

74-
public override void DrawButtonBorder(Graphics g, Rectangle bounds, PushButtonState state, bool isDefault)
78+
public override void DrawButtonBorder(Graphics g, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault)
7579
{
7680
g.SmoothingMode = SmoothingMode.AntiAlias;
7781

7882
// Win32 draws its stroke fully *inside* the control → inset by 1 px
7983
Rectangle outer = Rectangle.Inflate(bounds, -1, -1);
8084

81-
DrawSingleBorder(g, outer, GetBorderColor(state));
85+
DrawSingleBorder(g, outer, borderSize, GetBorderColor(state));
8286

8387
// Default button gets a second 1‑px border one pixel further inside
8488
if (isDefault)
8589
{
8690
Rectangle inner = Rectangle.Inflate(outer, -1, -1);
87-
DrawSingleBorder(g, inner, DefaultColors.AcceptFocusIndicatorBackColor);
91+
DrawSingleBorder(g, inner, borderSize, DefaultColors.AcceptFocusIndicatorBackColor);
8892
}
8993
}
9094

91-
private static void DrawSingleBorder(Graphics g, Rectangle rect, Color color)
95+
private static void DrawSingleBorder(Graphics g, Rectangle rect, int borderSize, Color color)
9296
{
9397
g.SmoothingMode = SmoothingMode.AntiAlias;
9498

95-
// a 1‑px stroke, aligned *inside*, is exactly what Win32 draws
96-
using var pen = new Pen(color) { Alignment = PenAlignment.Inset };
99+
using var pen = new Pen(color, borderSize) { Alignment = PenAlignment.Inset };
97100
g.DrawRectangle(pen, rect);
98101
}
99102

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/IButtonRenderer.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,27 @@ void RenderButton(
4343
Graphics graphics,
4444
Rectangle bounds,
4545
FlatStyle flatStyle,
46+
int BorderSize,
4647
PushButtonState state,
4748
bool isDefault,
4849
bool focused,
4950
bool showFocusCues,
5051
Color parentBackgroundColor,
5152
Color backColor,
5253
Action<Rectangle> paintImage,
54+
Action<Rectangle> paintBackgroundImage,
5355
Action paintField);
5456

5557
/// <summary>
5658
/// Draws button background with appropriate styling.
5759
/// </summary>
5860
/// <param name="graphics">Graphics context to draw on</param>
5961
/// <param name="bounds">Bounds of the button</param>
62+
/// <param name="borderSize">BorderSize of the button</param>
6063
/// <param name="state">State of the button (normal, hot, pressed, disabled)</param>
6164
/// <param name="isDefault">True if button is the default button</param>
6265
/// <returns>The content bounds (area inside the button for text/image)</returns>
63-
Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault, Color backColor);
66+
Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault, Color backColor);
6467

6568
/// <summary>
6669
/// Draws focus indicator appropriate for this style.

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/PopupButtonDarkModeRenderer.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ internal class PopupButtonDarkModeRenderer : ButtonDarkModeRendererBase
3030
/// <summary>
3131
/// Draws button background with popup styling, including subtle 3D effect.
3232
/// </summary>
33-
public override Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault, Color backColor)
33+
public override Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault, Color backColor)
3434
{
3535
// Use padding from ButtonDarkModeRenderer
3636
Padding padding = PaddingCore;
37-
Rectangle paddedBounds = Rectangle.Inflate(bounds, -padding.Left, -padding.Top);
37+
Rectangle paddedBounds = Rectangle.Inflate(bounds, -1 - padding.Left, -1 - padding.Top);
3838

3939
// Content rect will be used to position text and images
4040
Rectangle contentBounds = Rectangle.Inflate(paddedBounds, -padding.Left, -padding.Top);
@@ -117,7 +117,7 @@ public override Color GetBackgroundColor(PushButtonState state, bool isDefault)
117117
/// <summary>
118118
/// Draws the 3D effect border for the button.
119119
/// </summary>
120-
public override void DrawButtonBorder(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault)
120+
public override void DrawButtonBorder(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault)
121121
{
122122
// Save original smoothing mode to restore later
123123
SmoothingMode originalMode = graphics.SmoothingMode;

src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/SystemButtonDarkModeRenderer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ internal class SystemButtonDarkModeRenderer : ButtonDarkModeRendererBase
3030
/// <summary>
3131
/// Draws button background with system styling (larger rounded corners).
3232
/// </summary>
33-
public override Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault, Color backColor)
33+
public override Rectangle DrawButtonBackground(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault, Color backColor)
3434
{
3535
// Shrink for DarkBorderGap and FocusBorderThickness
3636
Rectangle fillBounds = Rectangle.Inflate(bounds, -SystemStylePadding, -SystemStylePadding);
@@ -108,7 +108,7 @@ public override Color GetBackgroundColor(PushButtonState state, bool isDefault)
108108
_ => DefaultColors.StandardBackColor
109109
};
110110

111-
public override void DrawButtonBorder(Graphics graphics, Rectangle bounds, PushButtonState state, bool isDefault) =>
111+
public override void DrawButtonBorder(Graphics graphics, Rectangle bounds, int borderSize, PushButtonState state, bool isDefault) =>
112112
DrawButtonBorder(graphics, bounds, state, isDefault, false);
113113

114114
/// <summary>

0 commit comments

Comments
 (0)