Skip to content

Commit 36f3117

Browse files
committed
fixup! Do not reset user fonts in DataGridView
1 parent 9b6bcab commit 36f3117

File tree

8 files changed

+245
-112
lines changed

8 files changed

+245
-112
lines changed

src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/EmfScope.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.Generic;
88
using System.Numerics;
99
using System.Runtime.InteropServices;
10+
using System.Text;
1011
using static Interop;
1112

1213
namespace System.Windows.Forms.Metafiles
@@ -167,16 +168,16 @@ bool stateTracker(ref EmfRecord record)
167168
}
168169
}
169170

170-
public List<string> RecordsToString()
171+
public string RecordsToString()
171172
{
172-
var strings = new List<string>();
173+
var strings = new StringBuilder();
173174
Enumerate((ref EmfRecord record) =>
174175
{
175-
strings.Add(record.ToString());
176+
strings.AppendLine(record.ToString());
176177
return true;
177178
});
178179

179-
return strings;
180+
return strings.ToString();
180181
}
181182

182183
public List<string> RecordsToStringWithState(DeviceContextState state)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#nullable enable
6+
7+
using Xunit;
8+
9+
namespace System.Windows.Forms.Metafiles
10+
{
11+
internal class FontFaceNameValidator : IStateValidator
12+
{
13+
private readonly string _fontFaceName;
14+
15+
/// <param name="fontFaceName">The font face name to validate.</param>
16+
public FontFaceNameValidator(string fontFaceName) => _fontFaceName = fontFaceName;
17+
18+
public void Validate(DeviceContextState state) => Assert.Equal(_fontFaceName, state.SelectedFont.FaceName.ToString());
19+
}
20+
}

src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/State.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,18 @@ namespace System.Windows.Forms.Metafiles
1212
{
1313
internal static class State
1414
{
15-
internal static IStateValidator TextColor(Color textColor) => new TextColorValidator(textColor);
15+
internal static IStateValidator Brush(Color brushColor, Gdi32.BS brushStyle)
16+
=> new BrushValidator(brushColor, brushStyle);
17+
internal static IStateValidator BrushColor(Color brushColor) => new BrushColorValidator(brushColor);
18+
internal static IStateValidator BrushStyle(Gdi32.BS brushStyle) => new BrushStyleValidator(brushStyle);
19+
internal static IStateValidator FontFace(string fontFaceName) => new FontFaceNameValidator(fontFaceName);
1620
internal static IStateValidator Pen(int penWidth, Color penColor, Gdi32.PS penStyle)
1721
=> new PenValidator(penWidth, penColor, penStyle);
1822
internal static IStateValidator PenColor(Color penColor) => new PenColorValidator(penColor);
1923
internal static IStateValidator PenStyle(Gdi32.PS penStyle) => new PenStyleValidator(penStyle);
2024
internal static IStateValidator PenWidth(int penWidth) => new PenWidthValidator(penWidth);
21-
internal static IStateValidator Brush(Color brushColor, Gdi32.BS brushStyle)
22-
=> new BrushValidator(brushColor, brushStyle);
23-
internal static IStateValidator BrushColor(Color brushColor) => new BrushColorValidator(brushColor);
24-
internal static IStateValidator BrushStyle(Gdi32.BS brushStyle) => new BrushStyleValidator(brushStyle);
2525
internal static IStateValidator Rop2(Gdi32.R2 rop2Mode) => new Rop2Validator(rop2Mode);
26+
internal static IStateValidator TextColor(Color textColor) => new TextColorValidator(textColor);
2627
internal static IStateValidator Transform(Matrix3x2 transform) => new TransformValidator(transform);
2728
}
2829
}

src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/TextOutValidator.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,17 @@ namespace System.Windows.Forms.Metafiles
1313
internal sealed class TextOutValidator : StateValidator
1414
{
1515
private readonly string? _text;
16-
private readonly string? _fontFace;
1716
private readonly Rectangle? _bounds;
1817

1918
/// <param name="text">Optional text to validate.</param>
2019
/// <param name="bounds">Optional bounds to validate.</param>
21-
/// <param name="fontFace">Optional font face name to validate.</param>
2220
/// <param name="stateValidators">Optional device context state validation to perform.</param>
2321
public TextOutValidator(
2422
string? text,
2523
Rectangle? bounds = default,
26-
string? fontFace = default,
2724
params IStateValidator[] stateValidators) : base(stateValidators)
2825
{
2926
_text = text;
30-
_fontFace = fontFace;
3127
_bounds = bounds;
3228
}
3329

@@ -51,11 +47,6 @@ public override unsafe void Validate(ref EmfRecord record, DeviceContextState st
5147
{
5248
Assert.Equal(_bounds.Value, (Rectangle)textOut->rclBounds);
5349
}
54-
55-
if (_fontFace != null)
56-
{
57-
Assert.Equal(_fontFace, state.SelectedFont.FaceName.ToString());
58-
}
5950
}
6051
}
6152
}

src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/Validate.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,13 @@ internal static IEmfValidator Polyline16(
3535

3636
/// <param name="text">Optional text to validate.</param>
3737
/// <param name="bounds">Optional bounds to validate.</param>
38-
/// <param name="fontFace">Optional font face name to validate.</param>
3938
/// <param name="stateValidators">Optional device context state validation to perform.</param>
4039
internal static IEmfValidator TextOut(
4140
string? text = default,
4241
Rectangle? bounds = default,
43-
string? fontFace = default,
4442
params IStateValidator[] stateValidators) => new TextOutValidator(
4543
text,
4644
bounds,
47-
fontFace,
4845
stateValidators);
4946

5047
/// <param name="from">Optional source point to validate.</param>
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Drawing;
6+
using System.Numerics;
7+
using System.Windows.Forms.Metafiles;
8+
using Xunit;
9+
using static System.Windows.Forms.Metafiles.DataHelpers;
10+
using static Interop;
11+
12+
namespace System.Windows.Forms.Tests
13+
{
14+
partial class DataGridViewTests
15+
{
16+
[WinFormsFact]
17+
public void DataGridView_GridColor_Rendering()
18+
{
19+
using Form form = new Form();
20+
21+
// Only want to render one cell to validate
22+
using var dataGrid = new DataGridView
23+
{
24+
GridColor = Color.Blue,
25+
ColumnCount = 1,
26+
RowCount = 1,
27+
ColumnHeadersVisible = false,
28+
RowHeadersVisible = false
29+
};
30+
31+
form.Controls.Add(dataGrid);
32+
33+
using var emf = new EmfScope();
34+
DeviceContextState state = new DeviceContextState(emf);
35+
36+
dataGrid.PrintToMetafile(emf);
37+
38+
Assert.Equal(new Rectangle(0, 0, 240, 150), dataGrid.Bounds);
39+
Assert.Equal(new Size(100, 25), dataGrid[0, 0].Size);
40+
41+
Rectangle bounds = dataGrid.Bounds;
42+
43+
// For whatever reason GDI+ renders as polylines scaled 16x with a 1/16th world transform applied.
44+
// For test readability we'll transform the points from our coordinates to the logical coordinates.
45+
Matrix3x2 oneSixteenth = Matrix3x2.CreateScale(0.0625f);
46+
Matrix3x2 times16 = Matrix3x2.CreateScale(16.0f);
47+
48+
// This is the default pen style GDI+ renders with
49+
Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT
50+
| Gdi32.PS.JOIN_MITER | Gdi32.PS.GEOMETRIC;
51+
52+
// Don't really care about the bounds, just the actual shapes/lines
53+
emf.Validate(
54+
state,
55+
// The datagrid background
56+
Validate.Polygon16(
57+
bounds: null,
58+
PointArray(times16, 1, 1, 1, 149, 239, 149, 239, 1, 1, 1),
59+
State.Pen(1, Color.Empty, Gdi32.PS.NULL),
60+
State.Brush(SystemColors.ButtonShadow, Gdi32.BS.SOLID),
61+
State.Transform(oneSixteenth)),
62+
// Left cell border
63+
Validate.Polyline16(
64+
bounds: null,
65+
PointArray(times16, 1, 1, 1, 26),
66+
State.Pen(16, Color.Blue, penStyle),
67+
State.Transform(oneSixteenth)),
68+
// Right cell border
69+
Validate.Polyline16(
70+
bounds: null,
71+
PointArray(times16, 101, 1, 101, 26),
72+
State.Pen(16, Color.Blue, penStyle),
73+
State.Transform(oneSixteenth)),
74+
// Top cell border
75+
Validate.Polyline16(
76+
bounds: null,
77+
PointArray(times16, 1, 1, 101, 1),
78+
State.Pen(16, Color.Blue, penStyle),
79+
State.Transform(oneSixteenth)),
80+
// Bottom cell border
81+
Validate.Polyline16(
82+
bounds: null,
83+
PointArray(times16, 1, 26, 101, 26),
84+
State.Pen(16, Color.Blue, penStyle),
85+
State.Transform(oneSixteenth)),
86+
// Cell background
87+
Validate.Polygon16(
88+
bounds: null,
89+
PointArray(times16, 2, 2, 2, 26, 101, 26, 101, 2, 2, 2),
90+
State.Pen(1, Color.Empty, Gdi32.PS.NULL),
91+
State.Brush(SystemColors.ButtonHighlight, Gdi32.BS.SOLID),
92+
State.Transform(oneSixteenth)),
93+
// Datagrid border
94+
Validate.Polygon16(
95+
bounds: null,
96+
PointArray(times16, 0, 0, 239, 0, 239, 149, 0, 149),
97+
State.Pen(16, SystemColors.Desktop, penStyle),
98+
State.Brush(Color.Empty, Gdi32.BS.NULL),
99+
State.Transform(oneSixteenth)));
100+
}
101+
102+
[WinFormsFact]
103+
public void DataGridView_DefaultCellStyles_Rendering()
104+
{
105+
#region DataGridView setup
106+
107+
using Font formFont1 = new Font("Times New Roman", 12F, FontStyle.Regular);
108+
using Form form = new Form
109+
{
110+
Font = formFont1,
111+
Size = new Size(700, 200)
112+
};
113+
114+
using Font customCellStyleFont = new Font("Tahoma", 8.25F, FontStyle.Regular);
115+
using Font customColumnHeaderFont = new Font("Consolas", 14F, FontStyle.Italic);
116+
using Font customRowHeaderFont = new Font("Arial", 9F, FontStyle.Bold);
117+
118+
var defaultCellStyle = new DataGridViewCellStyle
119+
{
120+
Font = customCellStyleFont,
121+
122+
// We must supply a completely initialised instance, else we'd be receiving a copy
123+
// refer to DefaultCellStyle implementation
124+
125+
Alignment = DataGridViewContentAlignment.MiddleLeft,
126+
BackColor = SystemColors.Info,
127+
ForeColor = Color.Maroon,
128+
SelectionBackColor = SystemColors.Highlight,
129+
SelectionForeColor = SystemColors.HighlightText,
130+
WrapMode = DataGridViewTriState.False
131+
};
132+
133+
using DataGridView dataGridView = new DataGridView
134+
{
135+
DefaultCellStyle = defaultCellStyle,
136+
ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customColumnHeaderFont },
137+
RowHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customRowHeaderFont },
138+
139+
Dock = DockStyle.Fill,
140+
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize,
141+
};
142+
143+
var column1 = new DataGridViewTextBoxColumn { HeaderText = "Style" };
144+
var column2 = new DataGridViewTextBoxColumn { HeaderText = "Font" };
145+
dataGridView.Columns.AddRange(new[] { column1, column2, });
146+
dataGridView.Rows.Add(nameof(DataGridView.DefaultCellStyle), customCellStyleFont.ToString());
147+
dataGridView.Rows.Add(nameof(DataGridView.ColumnHeadersDefaultCellStyle), customColumnHeaderFont.ToString());
148+
dataGridView.Rows.Add(nameof(DataGridView.RowHeadersDefaultCellStyle), customRowHeaderFont.ToString());
149+
for (int i = 0; i < dataGridView.Rows.Count; i++)
150+
{
151+
dataGridView.Rows[i].HeaderCell.Value = $"Row {i + 1}";
152+
}
153+
154+
dataGridView.RowHeadersWidth = 100;
155+
156+
Assert.Same(customCellStyleFont, dataGridView.DefaultCellStyle.Font);
157+
Assert.Same(customColumnHeaderFont, dataGridView.ColumnHeadersDefaultCellStyle.Font);
158+
Assert.Same(customRowHeaderFont, dataGridView.RowHeadersDefaultCellStyle.Font);
159+
160+
// Add the datagridview to the form, this will trigger Font change via OnFontChanged
161+
form.Controls.Add(dataGridView);
162+
163+
#endregion
164+
165+
using var emf = new EmfScope();
166+
DeviceContextState state = new DeviceContextState(emf);
167+
168+
Assert.NotEqual(IntPtr.Zero, dataGridView.Handle);
169+
dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
170+
171+
dataGridView.PrintToMetafile(emf);
172+
173+
// We only care about font styles, nothihg else
174+
emf.Validate(
175+
state,
176+
177+
// Column headers
178+
Validate.SkipTo(
179+
Validate.TextOut(column1.HeaderText, stateValidators: State.FontFace(customColumnHeaderFont.Name))),
180+
Validate.SkipTo(
181+
Validate.TextOut(column2.HeaderText, stateValidators: State.FontFace(customColumnHeaderFont.Name))),
182+
183+
// Row1
184+
Validate.SkipTo(
185+
Validate.TextOut("Row 1", stateValidators: State.FontFace(customRowHeaderFont.Name))),
186+
Validate.SkipTo(
187+
Validate.TextOut(nameof(DataGridView.DefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))),
188+
Validate.SkipTo(
189+
Validate.TextOut(customCellStyleFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))),
190+
191+
// Row2
192+
Validate.SkipTo(
193+
Validate.TextOut("Row 2", stateValidators: State.FontFace(customRowHeaderFont.Name))),
194+
Validate.SkipTo(
195+
Validate.TextOut(nameof(DataGridView.ColumnHeadersDefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))),
196+
Validate.SkipTo(
197+
Validate.TextOut(customColumnHeaderFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))),
198+
199+
// Row3
200+
Validate.SkipTo(
201+
Validate.TextOut("Row 3", stateValidators: State.FontFace(customRowHeaderFont.Name))),
202+
Validate.SkipTo(
203+
Validate.TextOut(nameof(DataGridView.RowHeadersDefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))),
204+
Validate.SkipTo(
205+
Validate.TextOut(customRowHeaderFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))),
206+
207+
Validate.SkipAll());
208+
}
209+
}
210+
}

0 commit comments

Comments
 (0)