Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,12 @@ internal static HighDpiMode GetThreadHighDpiMode()
/// <summary>
/// Get X, Y metrics at DPI, IF icon is not already that size, create and return a new one.
/// </summary>
internal static Icon ScaleSmallIconToDpi(Icon icon, int dpi)
internal static Icon ScaleSmallIconToDpi(Icon icon, int dpi, bool alwaysCreateNew = false)
{
int width = PInvoke.GetCurrentSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSMICON, (uint)dpi);
int height = PInvoke.GetCurrentSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSMICON, (uint)dpi);

return (icon.Width == width && icon.Height == height) ? icon : new(icon, width, height);
return (icon.Width == width && icon.Height == height && !alwaysCreateNew) ? icon : new(icon, width, height);
}

/// <summary>
Expand Down
13 changes: 6 additions & 7 deletions src/System.Windows.Forms/System/Windows/Forms/Form.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6453,11 +6453,14 @@ private unsafe void UpdateWindowIcon(bool redrawFrame, int dpi = 0)

if (icon is not null)
{
Icon? oldSmallIcon = _smallIcon;

try
{
_smallIcon = ScaleHelper.ScaleSmallIconToDpi(icon, dpi);
// As we dispose the _smallIcon in multiple places, we'd need to track when we've
// actually created a scaled icon to know when we should free it selectively (so we
// don't free user provided Icons. For now, just always create a new scaled icon.
_smallIcon?.Dispose();
_smallIcon = null;
_smallIcon = ScaleHelper.ScaleSmallIconToDpi(icon, dpi, alwaysCreateNew: true);
}
catch
{
Expand All @@ -6466,10 +6469,6 @@ private unsafe void UpdateWindowIcon(bool redrawFrame, int dpi = 0)
if (_smallIcon is not null)
{
PInvokeCore.SendMessage(this, PInvokeCore.WM_SETICON, (WPARAM)PInvoke.ICON_SMALL, (LPARAM)_smallIcon.Handle);
if (oldSmallIcon is not null && oldSmallIcon.Handle != _smallIcon.Handle)
{
oldSmallIcon.Dispose();
}
}

PInvokeCore.SendMessage(this, PInvokeCore.WM_SETICON, (WPARAM)PInvoke.ICON_BIG, (LPARAM)icon.Handle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2748,6 +2748,21 @@ public void Form_DoesNot_PreventShutDown()
Assert.True((BOOL)message.ResultInternal);
}

[WinFormsFact]
public void Form_DoesNot_DisposeUserIcon()
{
// https://github.com/dotnet/winforms/issues/13963
using Form form = new();
int dpi = form.DeviceDpi;
using Icon icon = new(typeof(Form), "wfc");
int smallDpi = PInvoke.GetCurrentSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSMICON, (uint)dpi);
using Icon smallIcon = new(icon, new Size(smallDpi, smallDpi));
form.Icon = smallIcon;
form.Show();
form.Close();
smallIcon.Handle.Should().NotBe(0);
}

public partial class ParentedForm : Form
{
private ParentingForm _parentForm;
Expand Down
Loading