Skip to content

Commit

Permalink
fix PropertyGrid value rendering
Browse files Browse the repository at this point in the history
The fix introduced in dotnet#4525 has redirected the `PropertyGrid` value
rendering through a different code path which only relies on flags passed
into `DrawTextInternal` completely side-stepping any modifications applied
to the `Graphics` object. However the `PropertyGrid` value rendering
routines do modify the `Graphics` object (applying clipping and
transformations) but do not pass the necessary flags to `DrawTextInternal`.

Fix by applying the necessary flags to preserve the `Graphics` modifications,
and add debug-time asserts to check that necessary flags are applies,
if the underlying `Graphics` object is modified.

Fixes dotnet#4593

(cherry picked from commit 34cdcf6)
  • Loading branch information
RussKie committed Mar 2, 2021
1 parent 937b05a commit f828c9f
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2389,7 +2389,7 @@ public virtual void PaintValue(object val, Graphics g, Rectangle rect, Rectangle
textRectangle,
textColor,
backColor,
(TextFormatFlags)format);
(TextFormatFlags)format | PropertyGrid.MeasureTextHelper.GetTextRendererFlags());

ValueToolTipLocation = doToolTip ? new Point(rect.X + 2, rect.Y - 1) : InvalidPoint;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// 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.Diagnostics;
using System.Drawing;
using System.Drawing.Text;
using static Interop;
Expand Down Expand Up @@ -603,7 +604,7 @@ private static Gdi32.QUALITY GetDefaultFontQuality()
/// </summary>
private static ApplyGraphicsProperties GetApplyStateFlags(IDeviceContext deviceContext, TextFormatFlags textFormatFlags)
{
if (deviceContext is not Graphics)
if (deviceContext is not Graphics graphics)
{
return ApplyGraphicsProperties.None;
}
Expand All @@ -619,6 +620,16 @@ private static ApplyGraphicsProperties GetApplyStateFlags(IDeviceContext deviceC
apply |= ApplyGraphicsProperties.TranslateTransform;
}

Debug.Assert(apply.HasFlag(ApplyGraphicsProperties.Clipping)
|| graphics.Clip is null
|| graphics.Clip.GetHrgn(graphics) == IntPtr.Zero,
"Must preserve Graphics clipping region!");

Debug.Assert(apply.HasFlag(ApplyGraphicsProperties.TranslateTransform)
|| graphics.Transform is null
|| graphics.Transform.IsIdentity,
"Must preserve Graphics transformation!");

return apply;
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.Windows.Forms.Metafiles;
using System.Windows.Forms.PropertyGridInternal;
using Xunit;

namespace System.Windows.Forms.Tests
{
public partial class PropertyGridViewTests
{
[WinFormsFact]
public void PropertyGridView_Render_Labels_Values_Correctly()
{
Point pt = default(Point);
using PropertyGrid propertyGrid = new()
{
SelectedObject = pt,
Size = new(300, 200),
Visible = true
};

PropertyGridView propertyGridView = propertyGrid.TestAccessor().GridView;

// For us to be able to render PropertyGridView and its values
// PropertyGrid must be visible and have a valid handle.
// To be Visible is must either be visible (we don't want this in tests) or
// have no parent - so we can't add it to another control (such as a form).
propertyGrid.CreateControl();

using var emf = new EmfScope();
DeviceContextState state = new(emf);

propertyGridView.PrintToMetafile(emf);

// Only care about text: labels and values
emf.Validate(
state,

// Category: Misc
Validate.SkipTo(
Validate.TextOut("Misc", new(25, 4, 25, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),

// Value for "X"
Validate.SkipTo(
Validate.TextOut(" ", new(145, 22, 5, 14))), // blank??
Validate.SkipTo(
Validate.TextOut(pt.X.ToString(), new(145, 22, 5, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),
// Label for "X"
Validate.SkipTo(
Validate.TextOut(nameof(Point.X), new(25, 23, 6, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),

// Value for "Y"
Validate.SkipTo(
Validate.TextOut(" ", new(145, 41, 5, 14))), // blank??
Validate.SkipTo(
Validate.TextOut(pt.Y.ToString(), new(145, 41, 5, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),
// Label for "Y"
Validate.SkipTo(
Validate.TextOut(nameof(Point.Y), new(25, 42, 6, 14), stateValidators: State.FontFace(Control.DefaultFont.Name))),

Validate.SkipAll());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
// See the LICENSE file in the project root for more information.

using Xunit;
using WinForms.Common.Tests;

namespace System.Windows.Forms.PropertyGridInternal.Tests
{
public class PropertyGridViewTests
public partial class PropertyGridViewTests
{
[WinFormsFact]
public void PropertyGridView_created_for_PropertyGrid()
public void PropertyGridView_Ctor_Default()
{
using PropertyGrid propertyGrid = new PropertyGrid();
using PropertyGrid propertyGrid = new();
PropertyGridView propertyGridView = propertyGrid.TestAccessor().GridView;

// TODO: validate properties

Assert.NotNull(propertyGridView);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace System.Windows.Forms.Tests
using Point = System.Drawing.Point;
using Size = System.Drawing.Size;

public class PropertyGridTests : IClassFixture<ThreadExceptionFixture>
public partial class PropertyGridTests : IClassFixture<ThreadExceptionFixture>
{
[WinFormsFact]
public void PropertyGrid_Ctor_Default()
Expand Down Expand Up @@ -169,6 +169,9 @@ public void PropertyGrid_Ctor_Default()
Assert.False(control.VScroll);
Assert.Equal(130, control.Width);

PropertyGridView propertyGridView = control.TestAccessor().GridView;
Assert.NotNull(propertyGridView);

Assert.False(control.IsHandleCreated);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,10 @@ public void TextRenderer_DrawText_ApplyState(TextFormatFlags flags, Rectangle ex
using Region region = new(new Rectangle(1, 2, 6, 8));
graphics.Clip = region;

// We have modified graphics, but several tests don't set all the flags
// TextRenderer asserts for to ensure integrity.
using NoAssertContext noAssertContext = new();

TextRenderer.DrawText(
graphics,
"Landshark",
Expand Down Expand Up @@ -894,6 +898,10 @@ public void TextRenderer_MeasureText_ApplyState(TextFormatFlags flags, Size expe
using Region region = new(new Rectangle(1, 2, 6, 8));
graphics.Clip = region;

// We have modified graphics, but several tests don't set all the flags
// TextRenderer asserts for to ensure integrity.
using NoAssertContext noAssertContext = new();

Size size = TextRenderer.MeasureText(
graphics,
"Landshark",
Expand Down

0 comments on commit f828c9f

Please sign in to comment.