-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix Issue 14721: TreeView.CustomDraw leaks one HFONT per visible item per paint when NodeFont is set, leading to GDI handle exhaustion and crash #14730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| #nullable disable | ||
|
|
||
| using System.Drawing; | ||
| using System.Reflection; | ||
| using System.Runtime.Serialization.Formatters.Binary; | ||
| using System.Windows.Forms.TestUtilities; | ||
|
|
||
|
|
@@ -56,6 +57,24 @@ public void OwnerDrawPropertyBag_Font_Set_GetReturnsExpected(Font value) | |
| Assert.Equal(value is null, bag.IsEmpty()); | ||
| } | ||
|
|
||
| [WinFormsFact] | ||
| public void OwnerDrawPropertyBag_Font_SetDifferentValue_ResetsCachedFontWrapper() | ||
| { | ||
| using SubTreeView treeView = new(); | ||
| OwnerDrawPropertyBag bag = treeView.GetItemRenderStyles(null, 0); | ||
| using Font firstFont = new(SystemFonts.MenuFont, FontStyle.Regular); | ||
| using Font secondFont = new(SystemFonts.MenuFont, FontStyle.Bold); | ||
|
|
||
| bag.Font = firstFont; | ||
| _ = bag.GetType().GetProperty("FontHandle", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(bag); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| FieldInfo fontWrapperField = bag.GetType().GetField("_fontWrapper", BindingFlags.Instance | BindingFlags.NonPublic)!; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using TestAccessor.Dynamic instead of reflection. |
||
| Assert.NotNull(fontWrapperField.GetValue(bag)); | ||
|
|
||
| bag.Font = secondFont; | ||
| Assert.Null(fontWrapperField.GetValue(bag)); | ||
| } | ||
|
|
||
| [WinFormsTheory] | ||
| [CommonMemberData(typeof(CommonTestHelper), nameof(CommonTestHelper.GetColorWithEmptyTheoryData))] | ||
| public void OwnerDrawPropertyBag_ForeColor_Set_GetReturnsExpected(Color value) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
node._propBag.Font is not nullpart is redundant with the higher-level checkrenderinfo.Font is not null.GetItemRenderStylessetsretval.Font = node._propBag.Font(same reference) and returns an empty bag (Font == null) whenevernode/node._propBagis null, so oncerenderinfo.Font is not nullholds,node._propBag.Fontis guaranteed non-null too and this inner check can be dropped. (Keep thenode._propBag is not nullhalf only to satisfy the compiler's nullable analysis, which can't infer that invariant across the method boundary.)