diff --git a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/EmfScope.cs b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/EmfScope.cs index 9933584701b..e199b0ebad6 100644 --- a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/EmfScope.cs +++ b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/EmfScope.cs @@ -4,9 +4,9 @@ #nullable enable -using System.Collections.Generic; using System.Numerics; using System.Runtime.InteropServices; +using System.Text; using static Interop; namespace System.Windows.Forms.Metafiles @@ -167,29 +167,29 @@ bool stateTracker(ref EmfRecord record) } } - public List RecordsToString() + public string RecordsToString() { - var strings = new List(); + StringBuilder sb = new StringBuilder(1024); Enumerate((ref EmfRecord record) => { - strings.Add(record.ToString()); + sb.AppendLine(record.ToString()); return true; }); - return strings; + return sb.ToString(); } - public List RecordsToStringWithState(DeviceContextState state) + public string RecordsToStringWithState(DeviceContextState state) { - var strings = new List(); + StringBuilder sb = new StringBuilder(1024); EnumerateWithState((ref EmfRecord record, DeviceContextState state) => { - strings.Add(record.ToString(state)); + sb.AppendLine(record.ToString(state)); return true; }, state); - return strings; + return sb.ToString(); } private static unsafe BOOL CallBack( diff --git a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/FontFaceNameValidator.cs b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/FontFaceNameValidator.cs new file mode 100644 index 00000000000..986c749f419 --- /dev/null +++ b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/FontFaceNameValidator.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using Xunit; + +namespace System.Windows.Forms.Metafiles +{ + internal class FontFaceNameValidator : IStateValidator + { + private readonly string _fontFaceName; + + /// The font face name to validate. + public FontFaceNameValidator(string fontFaceName) => _fontFaceName = fontFaceName; + + public void Validate(DeviceContextState state) => Assert.Equal(_fontFaceName, state.SelectedFont.FaceName.ToString()); + } +} diff --git a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/State.cs b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/State.cs index c89d75a6599..e5dc8ea5ffe 100644 --- a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/State.cs +++ b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/State.cs @@ -12,17 +12,18 @@ namespace System.Windows.Forms.Metafiles { internal static class State { - internal static IStateValidator TextColor(Color textColor) => new TextColorValidator(textColor); + internal static IStateValidator Brush(Color brushColor, Gdi32.BS brushStyle) + => new BrushValidator(brushColor, brushStyle); + internal static IStateValidator BrushColor(Color brushColor) => new BrushColorValidator(brushColor); + internal static IStateValidator BrushStyle(Gdi32.BS brushStyle) => new BrushStyleValidator(brushStyle); + internal static IStateValidator FontFace(string fontFaceName) => new FontFaceNameValidator(fontFaceName); internal static IStateValidator Pen(int penWidth, Color penColor, Gdi32.PS penStyle) => new PenValidator(penWidth, penColor, penStyle); internal static IStateValidator PenColor(Color penColor) => new PenColorValidator(penColor); internal static IStateValidator PenStyle(Gdi32.PS penStyle) => new PenStyleValidator(penStyle); internal static IStateValidator PenWidth(int penWidth) => new PenWidthValidator(penWidth); - internal static IStateValidator Brush(Color brushColor, Gdi32.BS brushStyle) - => new BrushValidator(brushColor, brushStyle); - internal static IStateValidator BrushColor(Color brushColor) => new BrushColorValidator(brushColor); - internal static IStateValidator BrushStyle(Gdi32.BS brushStyle) => new BrushStyleValidator(brushStyle); internal static IStateValidator Rop2(Gdi32.R2 rop2Mode) => new Rop2Validator(rop2Mode); + internal static IStateValidator TextColor(Color textColor) => new TextColorValidator(textColor); internal static IStateValidator Transform(Matrix3x2 transform) => new TransformValidator(transform); } } diff --git a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/TextOutValidator.cs b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/TextOutValidator.cs index ce32f7c4ac9..8f006dcda36 100644 --- a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/TextOutValidator.cs +++ b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/TextOutValidator.cs @@ -13,21 +13,17 @@ namespace System.Windows.Forms.Metafiles internal sealed class TextOutValidator : StateValidator { private readonly string? _text; - private readonly string? _fontFace; private readonly Rectangle? _bounds; /// Optional text to validate. /// Optional bounds to validate. - /// Optional font face name to validate. /// Optional device context state validation to perform. public TextOutValidator( string? text, Rectangle? bounds = default, - string? fontFace = default, params IStateValidator[] stateValidators) : base(stateValidators) { _text = text; - _fontFace = fontFace; _bounds = bounds; } @@ -51,11 +47,6 @@ public override unsafe void Validate(ref EmfRecord record, DeviceContextState st { Assert.Equal(_bounds.Value, (Rectangle)textOut->rclBounds); } - - if (_fontFace != null) - { - Assert.Equal(_fontFace, state.SelectedFont.FaceName.ToString()); - } } } } diff --git a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/Validate.cs b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/Validate.cs index 23a53a65fe4..a80ecffedd3 100644 --- a/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/Validate.cs +++ b/src/System.Windows.Forms.Primitives/tests/TestUtilities/Metafiles/Validators/Validate.cs @@ -35,16 +35,13 @@ internal static IEmfValidator Polyline16( /// Optional text to validate. /// Optional bounds to validate. - /// Optional font face name to validate. /// Optional device context state validation to perform. internal static IEmfValidator TextOut( string? text = default, Rectangle? bounds = default, - string? fontFace = default, params IStateValidator[] stateValidators) => new TextOutValidator( text, bounds, - fontFace, stateValidators); /// Optional source point to validate. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs index c9049912296..435e0db6979 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/DataGridView.cs @@ -1612,6 +1612,10 @@ public DataGridViewCellStyle ColumnHeadersDefaultCellStyle { _columnHeadersDefaultCellStyle.AddScope(this, DataGridViewCellStyleScopes.ColumnHeaders); } + + // Update ambient font flag depending on cell style font + _dataGridViewState1[State1_AmbientColumnHeadersFont] = value?.Font == base.Font; + DataGridViewCellStyleDifferences dgvcsc = cs.GetDifferencesFrom(ColumnHeadersDefaultCellStyle); if (dgvcsc != DataGridViewCellStyleDifferences.None) { @@ -2128,6 +2132,10 @@ _defaultCellStyle.Font is null || { _defaultCellStyle.AddScope(this, DataGridViewCellStyleScopes.DataGridView); } + + // Update ambient font flag depending on cell style font + _dataGridViewState1[State1_AmbientFont] = value?.Font == base.Font; + DataGridViewCellStyleDifferences dgvcsc = cs.GetDifferencesFrom(DefaultCellStyle); if (dgvcsc != DataGridViewCellStyleDifferences.None) { @@ -3577,6 +3585,10 @@ public DataGridViewCellStyle RowHeadersDefaultCellStyle { _rowHeadersDefaultCellStyle.AddScope(this, DataGridViewCellStyleScopes.RowHeaders); } + + // Update ambient font flag depending on cell style font + _dataGridViewState1[State1_AmbientRowHeadersFont] = value?.Font == base.Font; + DataGridViewCellStyleDifferences dgvcsc = cs.GetDifferencesFrom(RowHeadersDefaultCellStyle); if (dgvcsc != DataGridViewCellStyleDifferences.None) { diff --git a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.Designer.cs b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.Designer.cs index 880e3461472..ec536298bf7 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.Designer.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.Designer.cs @@ -32,61 +32,162 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); this.dataGridView1 = new System.Windows.Forms.DataGridView(); this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.Column2 = new System.Windows.Forms.DataGridViewCheckBoxColumn(); - this.Column3 = new System.Windows.Forms.DataGridViewComboBoxColumn(); + this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Column3 = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.Column4 = new System.Windows.Forms.DataGridViewComboBoxColumn(); this.currentDPILabel1 = new WinformsControlsTest.CurrentDPILabel(); + this.button1 = new System.Windows.Forms.Button(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.label1 = new System.Windows.Forms.Label(); + this.button2 = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); this.SuspendLayout(); - // + // // dataGridView1 - // + // + dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control; + dataGridViewCellStyle1.Font = new System.Drawing.Font("Cascadia Code", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + this.dataGridView1.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.Column1, this.Column2, - this.Column3}); + this.Column3, + this.Column4}); + dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Info; + dataGridViewCellStyle3.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + dataGridViewCellStyle3.ForeColor = System.Drawing.Color.Maroon; + dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + this.dataGridView1.DefaultCellStyle = dataGridViewCellStyle3; + this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Top; this.dataGridView1.Location = new System.Drawing.Point(0, 0); this.dataGridView1.Name = "dataGridView1"; - this.dataGridView1.Size = new System.Drawing.Size(283, 150); + this.dataGridView1.Size = new System.Drawing.Size(492, 150); this.dataGridView1.TabIndex = 0; - // + // // Column1 - // + // this.Column1.HeaderText = "Column1"; this.Column1.Name = "Column1"; - // + // // Column2 - // + // this.Column2.HeaderText = "Column2"; this.Column2.Name = "Column2"; - // + // // Column3 - // + // this.Column3.HeaderText = "Column3"; this.Column3.Name = "Column3"; - // + // + // Column4 + // + this.Column4.HeaderText = "Column4"; + this.Column4.Name = "Column4"; + // // currentDPILabel1 - // - this.currentDPILabel1.Location = new System.Drawing.Point(0, 176); + // + this.currentDPILabel1.AutoSize = true; + this.currentDPILabel1.Location = new System.Drawing.Point(12, 174); this.currentDPILabel1.Name = "currentDPILabel1"; - this.currentDPILabel1.Size = new System.Drawing.Size(283, 23); + this.currentDPILabel1.Size = new System.Drawing.Size(116, 13); this.currentDPILabel1.TabIndex = 1; - this.currentDPILabel1.Text = "currentDPILabel1"; - // + this.currentDPILabel1.Text = "Current scaling is 100%"; + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button1.AutoSize = true; + this.button1.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + this.button1.Location = new System.Drawing.Point(12, 234); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(154, 29); + this.button1.TabIndex = 1; + this.button1.Text = "Change DGV font"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // numericUpDown1 + // + this.numericUpDown1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.numericUpDown1.Location = new System.Drawing.Point(89, 208); + this.numericUpDown1.Maximum = new decimal(new int[] { + 14, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 8, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(64, 20); + this.numericUpDown1.TabIndex = 2; + this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; + this.numericUpDown1.Value = new decimal(new int[] { + 8, + 0, + 0, + 0}); + this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 210); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(51, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Form font"; + // + // button2 + // + this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button2.AutoSize = true; + this.button2.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(204))); + this.button2.Location = new System.Drawing.Point(192, 234); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(154, 29); + this.button2.TabIndex = 4; + this.button2.Text = "Reset DGV font"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // // DataGridViewHeaders - // + // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.AutoSize = true; - this.ClientSize = new System.Drawing.Size(284, 221); + this.ClientSize = new System.Drawing.Size(492, 272); + this.Controls.Add(this.button2); + this.Controls.Add(this.label1); + this.Controls.Add(this.numericUpDown1); this.Controls.Add(this.currentDPILabel1); + this.Controls.Add(this.button1); this.Controls.Add(this.dataGridView1); + this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); this.Name = "DataGridViewHeaders"; this.Text = "DataGridView"; ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); this.ResumeLayout(false); + this.PerformLayout(); } @@ -94,8 +195,13 @@ private void InitializeComponent() private System.Windows.Forms.DataGridView dataGridView1; private System.Windows.Forms.DataGridViewTextBoxColumn Column1; - private System.Windows.Forms.DataGridViewCheckBoxColumn Column2; - private System.Windows.Forms.DataGridViewComboBoxColumn Column3; - private CurrentDPILabel currentDPILabel1; + private System.Windows.Forms.DataGridViewTextBoxColumn Column2; + private System.Windows.Forms.DataGridViewCheckBoxColumn Column3; + private System.Windows.Forms.DataGridViewComboBoxColumn Column4; + private WinformsControlsTest.CurrentDPILabel currentDPILabel1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button2; } -} \ No newline at end of file +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.cs b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.cs index 15215460b17..a5ae84ff6be 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/WinformsControlsTest/DataGridViewHeaders.cs @@ -3,24 +3,43 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; using System.Drawing; -using System.Text; using System.Windows.Forms; namespace WinformsControlsTest { public partial class DataGridViewHeaders : Form { + private static readonly Font[] s_fonts = new Font[] + { + new Font("Tahoma", 12F, FontStyle.Regular), + new Font("Fira Code", 10F, FontStyle.Bold), + new Font("Consolas", 14F, FontStyle.Italic), + new Font("Arial", 9F, FontStyle.Bold), + new Font("Microsoft Sans Serif", 11F, FontStyle.Regular), + }; + private int _cellFontIndex; + private int _columnHeaderFontIndex; + private int _rowHeaderFontIndex; + public DataGridViewHeaders() { InitializeComponent(); + + dataGridView1.Rows.Add("DefaultCellStyle", dataGridView1.DefaultCellStyle.Font.ToString()); + dataGridView1.Rows.Add("ColumnHeadersDefaultCellStyle", dataGridView1.ColumnHeadersDefaultCellStyle.Font.ToString()); + dataGridView1.Rows.Add("RowHeadersDefaultCellStyle", dataGridView1.RowHeadersDefaultCellStyle.Font.ToString()); + + for (int i = 0; i < dataGridView1.Rows.Count; i++) + { + dataGridView1.Rows[i].HeaderCell.Value = $"Row {i + 1}"; + } } - private void DataGridView_Load(object sender, EventArgs e) + protected override void OnLoad(EventArgs e) { + base.OnLoad(e); + currentDPILabel1.Text = DeviceDpi.ToString(); } @@ -28,5 +47,47 @@ private void DataGridView_DpiChanged(object sender, DpiChangedEventArgs e) { currentDPILabel1.Text = DeviceDpi.ToString(); } + + private void button1_Click(object sender, EventArgs e) + { + _cellFontIndex++; + if (_cellFontIndex >= s_fonts.Length) + { + _cellFontIndex -= s_fonts.Length; + } + + _columnHeaderFontIndex += 2; + if (_columnHeaderFontIndex >= s_fonts.Length) + { + _columnHeaderFontIndex -= s_fonts.Length; + } + + _rowHeaderFontIndex += 3; + if (_rowHeaderFontIndex >= s_fonts.Length) + { + _rowHeaderFontIndex -= s_fonts.Length; + } + + dataGridView1.DefaultCellStyle.Font = s_fonts[_cellFontIndex]; + dataGridView1.Rows[0].Cells[1].Value = s_fonts[_cellFontIndex]; + + dataGridView1.ColumnHeadersDefaultCellStyle.Font = s_fonts[_columnHeaderFontIndex]; + dataGridView1.Rows[1].Cells[1].Value = s_fonts[_columnHeaderFontIndex]; + + dataGridView1.RowHeadersDefaultCellStyle.Font = s_fonts[_rowHeaderFontIndex]; + dataGridView1.Rows[2].Cells[1].Value = s_fonts[_rowHeaderFontIndex]; + } + + private void button2_Click(object sender, EventArgs e) + { + dataGridView1.DefaultCellStyle.Font = null; + dataGridView1.ColumnHeadersDefaultCellStyle.Font = null; + dataGridView1.RowHeadersDefaultCellStyle.Font = null; + } + + private void numericUpDown1_ValueChanged(object sender, EventArgs e) + { + Font = new Font("Tahoma", (float)numericUpDown1.Value, FontStyle.Regular); + } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.Rendering.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.Rendering.cs new file mode 100644 index 00000000000..65291ebb6e1 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.Rendering.cs @@ -0,0 +1,210 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using System.Numerics; +using System.Windows.Forms.Metafiles; +using Xunit; +using static System.Windows.Forms.Metafiles.DataHelpers; +using static Interop; + +namespace System.Windows.Forms.Tests +{ + partial class DataGridViewTests + { + [WinFormsFact] + public void DataGridView_GridColor_Rendering() + { + using Form form = new Form(); + + // Only want to render one cell to validate + using var dataGrid = new DataGridView + { + GridColor = Color.Blue, + ColumnCount = 1, + RowCount = 1, + ColumnHeadersVisible = false, + RowHeadersVisible = false + }; + + form.Controls.Add(dataGrid); + + using var emf = new EmfScope(); + DeviceContextState state = new DeviceContextState(emf); + + dataGrid.PrintToMetafile(emf); + + Assert.Equal(new Rectangle(0, 0, 240, 150), dataGrid.Bounds); + Assert.Equal(new Size(100, 25), dataGrid[0, 0].Size); + + Rectangle bounds = dataGrid.Bounds; + + // For whatever reason GDI+ renders as polylines scaled 16x with a 1/16th world transform applied. + // For test readability we'll transform the points from our coordinates to the logical coordinates. + Matrix3x2 oneSixteenth = Matrix3x2.CreateScale(0.0625f); + Matrix3x2 times16 = Matrix3x2.CreateScale(16.0f); + + // This is the default pen style GDI+ renders with + Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT + | Gdi32.PS.JOIN_MITER | Gdi32.PS.GEOMETRIC; + + // Don't really care about the bounds, just the actual shapes/lines + emf.Validate( + state, + // The datagrid background + Validate.Polygon16( + bounds: null, + PointArray(times16, 1, 1, 1, 149, 239, 149, 239, 1, 1, 1), + State.Pen(1, Color.Empty, Gdi32.PS.NULL), + State.Brush(SystemColors.ButtonShadow, Gdi32.BS.SOLID), + State.Transform(oneSixteenth)), + // Left cell border + Validate.Polyline16( + bounds: null, + PointArray(times16, 1, 1, 1, 26), + State.Pen(16, Color.Blue, penStyle), + State.Transform(oneSixteenth)), + // Right cell border + Validate.Polyline16( + bounds: null, + PointArray(times16, 101, 1, 101, 26), + State.Pen(16, Color.Blue, penStyle), + State.Transform(oneSixteenth)), + // Top cell border + Validate.Polyline16( + bounds: null, + PointArray(times16, 1, 1, 101, 1), + State.Pen(16, Color.Blue, penStyle), + State.Transform(oneSixteenth)), + // Bottom cell border + Validate.Polyline16( + bounds: null, + PointArray(times16, 1, 26, 101, 26), + State.Pen(16, Color.Blue, penStyle), + State.Transform(oneSixteenth)), + // Cell background + Validate.Polygon16( + bounds: null, + PointArray(times16, 2, 2, 2, 26, 101, 26, 101, 2, 2, 2), + State.Pen(1, Color.Empty, Gdi32.PS.NULL), + State.Brush(SystemColors.ButtonHighlight, Gdi32.BS.SOLID), + State.Transform(oneSixteenth)), + // Datagrid border + Validate.Polygon16( + bounds: null, + PointArray(times16, 0, 0, 239, 0, 239, 149, 0, 149), + State.Pen(16, SystemColors.Desktop, penStyle), + State.Brush(Color.Empty, Gdi32.BS.NULL), + State.Transform(oneSixteenth))); + } + + [WinFormsFact] + public void DataGridView_DefaultCellStyles_Rendering() + { + #region DataGridView setup + + using Font formFont1 = new Font("Times New Roman", 12F, FontStyle.Regular); + using Form form = new Form + { + Font = formFont1, + Size = new Size(700, 200) + }; + + using Font customCellStyleFont = new Font("Tahoma", 8.25F, FontStyle.Regular); + using Font customColumnHeaderFont = new Font("Consolas", 14F, FontStyle.Italic); + using Font customRowHeaderFont = new Font("Arial", 9F, FontStyle.Bold); + + var defaultCellStyle = new DataGridViewCellStyle + { + Font = customCellStyleFont, + + // We must supply a completely initialised instance, else we'd be receiving a copy + // refer to DefaultCellStyle implementation + + Alignment = DataGridViewContentAlignment.MiddleLeft, + BackColor = SystemColors.Info, + ForeColor = Color.Maroon, + SelectionBackColor = SystemColors.Highlight, + SelectionForeColor = SystemColors.HighlightText, + WrapMode = DataGridViewTriState.False + }; + + using DataGridView dataGridView = new DataGridView + { + DefaultCellStyle = defaultCellStyle, + ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customColumnHeaderFont }, + RowHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customRowHeaderFont }, + + Dock = DockStyle.Fill, + ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize, + }; + + var column1 = new DataGridViewTextBoxColumn { HeaderText = "Style" }; + var column2 = new DataGridViewTextBoxColumn { HeaderText = "Font" }; + dataGridView.Columns.AddRange(new[] { column1, column2, }); + dataGridView.Rows.Add(nameof(DataGridView.DefaultCellStyle), customCellStyleFont.ToString()); + dataGridView.Rows.Add(nameof(DataGridView.ColumnHeadersDefaultCellStyle), customColumnHeaderFont.ToString()); + dataGridView.Rows.Add(nameof(DataGridView.RowHeadersDefaultCellStyle), customRowHeaderFont.ToString()); + for (int i = 0; i < dataGridView.Rows.Count; i++) + { + dataGridView.Rows[i].HeaderCell.Value = $"Row {i + 1}"; + } + + dataGridView.RowHeadersWidth = 100; + + Assert.Same(customCellStyleFont, dataGridView.DefaultCellStyle.Font); + Assert.Same(customColumnHeaderFont, dataGridView.ColumnHeadersDefaultCellStyle.Font); + Assert.Same(customRowHeaderFont, dataGridView.RowHeadersDefaultCellStyle.Font); + + // Add the datagridview to the form, this will trigger Font change via OnFontChanged + form.Controls.Add(dataGridView); + + #endregion + + using var emf = new EmfScope(); + DeviceContextState state = new DeviceContextState(emf); + + Assert.NotEqual(IntPtr.Zero, dataGridView.Handle); + dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); + + dataGridView.PrintToMetafile(emf); + + // We only care about font styles, nothihg else + emf.Validate( + state, + + // Column headers + Validate.SkipTo( + Validate.TextOut(column1.HeaderText, stateValidators: State.FontFace(customColumnHeaderFont.Name))), + Validate.SkipTo( + Validate.TextOut(column2.HeaderText, stateValidators: State.FontFace(customColumnHeaderFont.Name))), + + // Row1 + Validate.SkipTo( + Validate.TextOut("Row 1", stateValidators: State.FontFace(customRowHeaderFont.Name))), + Validate.SkipTo( + Validate.TextOut(nameof(DataGridView.DefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))), + Validate.SkipTo( + Validate.TextOut(customCellStyleFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))), + + // Row2 + Validate.SkipTo( + Validate.TextOut("Row 2", stateValidators: State.FontFace(customRowHeaderFont.Name))), + Validate.SkipTo( + Validate.TextOut(nameof(DataGridView.ColumnHeadersDefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))), + Validate.SkipTo( + Validate.TextOut(customColumnHeaderFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))), + + // Row3 + Validate.SkipTo( + Validate.TextOut("Row 3", stateValidators: State.FontFace(customRowHeaderFont.Name))), + Validate.SkipTo( + Validate.TextOut(nameof(DataGridView.RowHeadersDefaultCellStyle), stateValidators: State.FontFace(customCellStyleFont.Name))), + Validate.SkipTo( + Validate.TextOut(customRowHeaderFont.ToString(), stateValidators: State.FontFace(customCellStyleFont.Name))), + + Validate.SkipAll()); + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.cs index d66b8ae6e37..6168f1724f0 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataGridViewTests.cs @@ -14,7 +14,7 @@ namespace System.Windows.Forms.Tests { - public class DataGridViewTests : IClassFixture + public partial class DataGridViewTests : IClassFixture { [WinFormsFact] public void DataGridView_Ctor_Default() @@ -779,6 +779,33 @@ public void DataGridView_ColumnHeadersHeightSizeMode_SetInvalidValue_ThrowsInval Assert.Throws("value", () => control.ColumnHeadersHeightSizeMode = value); } + public static IEnumerable DefaultCellStyle_TestData() + { + // If any of the following properties are not initialised or set to the following values + // accessing DefaultCellStyle property will return a copy of cell styles, instead of the existing object + + yield return new object[] { new DataGridViewCellStyle() }; + yield return new object[] { new DataGridViewCellStyle { BackColor = Color.Empty } }; + yield return new object[] { new DataGridViewCellStyle { ForeColor = Color.Empty } }; + yield return new object[] { new DataGridViewCellStyle { SelectionBackColor = Color.Empty } }; + yield return new object[] { new DataGridViewCellStyle { SelectionForeColor = Color.Empty } }; + yield return new object[] { new DataGridViewCellStyle { Font = null } }; + yield return new object[] { new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.NotSet } }; + yield return new object[] { new DataGridViewCellStyle { WrapMode = DataGridViewTriState.NotSet } }; + } + + [WinFormsTheory] + [MemberData(nameof(DefaultCellStyle_TestData))] + public void DataGridView_DefaultCellStyle_returns_copy_if_not_all_fields_initialised(DataGridViewCellStyle cellStyle) + { + using DataGridView dataGridView = new DataGridView + { + DefaultCellStyle = cellStyle, + }; + + Assert.NotSame(cellStyle, dataGridView.DefaultCellStyle); + } + public static IEnumerable Parent_Set_TestData() { yield return new object[] { null }; @@ -2289,6 +2316,77 @@ public void DataGridView_OnColumnHeadersHeightSizeModeChanged_NullE_ThrowsNullRe Assert.Throws(() => control.OnColumnHeadersHeightSizeModeChanged(null)); } + [WinFormsFact] + [Trait("Issue", "https://github.com/dotnet/winforms/issues/3033")] + public void DataGridView_OnFontChanged_does_not_change_user_fonts() + { + using Font formFont1 = new Font("Times New Roman", 12F, FontStyle.Regular); + using Form form = new Form + { + Font = formFont1 + }; + + using Font customFont1 = new Font("Tahoma", 8.25F, FontStyle.Regular); + using Font customFont2 = new Font("Consolas", 14F, FontStyle.Italic); + using Font customFont3 = new Font("Arial", 9F, FontStyle.Bold); + + var defaultCellStyle = new DataGridViewCellStyle + { + Font = customFont1, + + // We must supply a completely initialised instance, else we'd be receiving a copy + // refer to DefaultCellStyle implementation + + Alignment = DataGridViewContentAlignment.MiddleLeft, + BackColor = SystemColors.Info, + ForeColor = Color.Maroon, + SelectionBackColor = SystemColors.Highlight, + SelectionForeColor = SystemColors.HighlightText, + WrapMode = DataGridViewTriState.False + }; + + using DataGridView dataGridView = new DataGridView + { + DefaultCellStyle = defaultCellStyle, + ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customFont2 }, + RowHeadersDefaultCellStyle = new DataGridViewCellStyle { Font = customFont3 } + }; + dataGridView.Columns.AddRange(new[] { new DataGridViewTextBoxColumn(), new DataGridViewTextBoxColumn() }); + dataGridView.Rows.Add("DefaultCellStyle", customFont1.ToString()); + dataGridView.Rows.Add("ColumnHeadersDefaultCellStyle", customFont2.ToString()); + dataGridView.Rows.Add("RowHeadersDefaultCellStyle", customFont3.ToString()); + + Assert.Same(customFont1, dataGridView.DefaultCellStyle.Font); + Assert.Same(customFont2, dataGridView.ColumnHeadersDefaultCellStyle.Font); + Assert.Same(customFont3, dataGridView.RowHeadersDefaultCellStyle.Font); + + // Add the datagridview to the form, this will trigger Font change via OnFontChanged + form.Controls.Add(dataGridView); + + // Ensure custom fonts are preserved + Assert.Same(customFont1, dataGridView.DefaultCellStyle.Font); + Assert.Same(customFont2, dataGridView.ColumnHeadersDefaultCellStyle.Font); + Assert.Same(customFont3, dataGridView.RowHeadersDefaultCellStyle.Font); + + // Force another global font change + using Font formFont2 = new Font("Arial Black", 10F, FontStyle.Italic); + form.Font = formFont2; + + // Ensure custom fonts are preserved + Assert.Same(customFont1, dataGridView.DefaultCellStyle.Font); + Assert.Same(customFont2, dataGridView.ColumnHeadersDefaultCellStyle.Font); + Assert.Same(customFont3, dataGridView.RowHeadersDefaultCellStyle.Font); + + // Ensure a user is still able to change datagridview fonts + dataGridView.DefaultCellStyle.Font = customFont2; + dataGridView.ColumnHeadersDefaultCellStyle.Font = customFont3; + dataGridView.RowHeadersDefaultCellStyle.Font = customFont1; + + Assert.Same(customFont2, dataGridView.DefaultCellStyle.Font); + Assert.Same(customFont3, dataGridView.ColumnHeadersDefaultCellStyle.Font); + Assert.Same(customFont1, dataGridView.RowHeadersDefaultCellStyle.Font); + } + public static IEnumerable OnRowHeadersWidthChanged_TestData() { foreach (DataGridViewRowHeadersWidthSizeMode rowHeadersWidthSizeMode in Enum.GetValues(typeof(DataGridViewRowHeadersWidthSizeMode))) @@ -2734,91 +2832,5 @@ public void DataGridView_GridColor() Assert.Equal(1, changedCount); Assert.Equal(Color.Red, dataGrid.GridColor); } - - [WinFormsFact] - public void DataGridView_GridColor_Rendering() - { - using Form form = new Form(); - - // Only want to render one cell to validate - using var dataGrid = new DataGridView - { - GridColor = Color.Blue, - ColumnCount = 1, - RowCount = 1, - ColumnHeadersVisible = false, - RowHeadersVisible = false - }; - - form.Controls.Add(dataGrid); - - using var emf = new EmfScope(); - DeviceContextState state = new DeviceContextState(emf); - - dataGrid.PrintToMetafile(emf); - - Assert.Equal(new Rectangle(0, 0, 240, 150), dataGrid.Bounds); - Assert.Equal(new Size(100, 25), dataGrid[0, 0].Size); - - Rectangle bounds = dataGrid.Bounds; - - // For whatever reason GDI+ renders as polylines scaled 16x with a 1/16th world transform applied. - // For test readability we'll transform the points from our coordinates to the logical coordinates. - Matrix3x2 oneSixteenth = Matrix3x2.CreateScale(0.0625f); - Matrix3x2 times16 = Matrix3x2.CreateScale(16.0f); - - // This is the default pen style GDI+ renders with - Gdi32.PS penStyle = Gdi32.PS.SOLID | Gdi32.PS.JOIN_ROUND | Gdi32.PS.COSMETIC | Gdi32.PS.ENDCAP_FLAT - | Gdi32.PS.JOIN_MITER | Gdi32.PS.GEOMETRIC; - - // Don't really care about the bounds, just the actual shapes/lines - emf.Validate( - state, - // The datagrid background - Validate.Polygon16( - bounds: null, - PointArray(times16, 1, 1, 1, 149, 239, 149, 239, 1, 1, 1), - State.Pen(1, Color.Empty, Gdi32.PS.NULL), - State.Brush(SystemColors.ButtonShadow, Gdi32.BS.SOLID), - State.Transform(oneSixteenth)), - // Left cell border - Validate.Polyline16( - bounds: null, - PointArray(times16, 1, 1, 1, 26), - State.Pen(16, Color.Blue, penStyle), - State.Transform(oneSixteenth)), - // Right cell border - Validate.Polyline16( - bounds: null, - PointArray(times16, 101, 1, 101, 26), - State.Pen(16, Color.Blue, penStyle), - State.Transform(oneSixteenth)), - // Top cell border - Validate.Polyline16( - bounds: null, - PointArray(times16, 1, 1, 101, 1), - State.Pen(16, Color.Blue, penStyle), - State.Transform(oneSixteenth)), - // Bottom cell border - Validate.Polyline16( - bounds: null, - PointArray(times16, 1, 26, 101, 26), - State.Pen(16, Color.Blue, penStyle), - State.Transform(oneSixteenth)), - // Cell background - Validate.Polygon16( - bounds: null, - PointArray(times16, 2, 2, 2, 26, 101, 26, 101, 2, 2, 2), - State.Pen(1, Color.Empty, Gdi32.PS.NULL), - State.Brush(SystemColors.ButtonHighlight, Gdi32.BS.SOLID), - State.Transform(oneSixteenth)), - // Datagrid border - Validate.Polygon16( - bounds: null, - PointArray(times16, 0, 0, 239, 0, 239, 149, 0, 149), - State.Pen(16, SystemColors.Desktop, penStyle), - State.Brush(Color.Empty, Gdi32.BS.NULL), - State.Transform(oneSixteenth))); - } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextRendererTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextRendererTests.cs index 7bd01d20d8d..8fa66ab2bed 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextRendererTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TextRendererTests.cs @@ -9,7 +9,6 @@ using Moq; using WinForms.Common.Tests; using Xunit; -using static Interop; namespace System.Windows.Forms.Tests { @@ -669,7 +668,7 @@ public unsafe void TextRenderer_DrawText_DefaultBackground_RendersTransparent(Fu Validate.TextOut( "Acrylic", bounds: null, // Don't care about the bounds for this test - fontFace: SystemFonts.DefaultFont.Name, + State.FontFace(SystemFonts.DefaultFont.Name), State.TextColor(Color.Blue))); } @@ -772,7 +771,7 @@ public unsafe void TextRenderer_DrawText_Padding_Point(TextFormatFlags flags, Re Validate.TextOut( "Sparkling Cider", expectedBounds, - SystemFonts.DefaultFont.Name, + State.FontFace(SystemFonts.DefaultFont.Name), State.TextColor(Color.Red))); } @@ -795,7 +794,7 @@ public unsafe void TextRenderer_DrawText_Padding_Rectangle(TextFormatFlags flags Validate.TextOut( "Sparkling Cider", expectedBounds, - SystemFonts.DefaultFont.Name, + State.FontFace(SystemFonts.DefaultFont.Name), State.TextColor(Color.Red))); }