|
| 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