Merge pull request #289 from Frassle/leak

[Win32] Fix leaks in Win32 Cursor property
This commit is contained in:
Fraser Waters 2015-08-10 22:01:42 +01:00
commit 3026154989
2 changed files with 48 additions and 14 deletions

View file

@ -1739,6 +1739,13 @@ namespace OpenTK.Platform.Windows
#endregion #endregion
#region DeleteObject
[DllImport("gdi32.dll", SetLastError = true)]
internal static extern BOOL DeleteObject([In]IntPtr hObject);
#endregion
#endregion #endregion
#region Timer Functions #region Timer Functions

View file

@ -1127,16 +1127,21 @@ namespace OpenTK.Platform.Windows
} }
set set
{ {
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value != cursor) if (value != cursor)
{ {
bool destoryOld = cursor != MouseCursor.Default; MouseCursor oldCursor = cursor;
IntPtr oldCursor = IntPtr.Zero; IntPtr oldCursorHandle = cursor_handle;
if (value == MouseCursor.Default) if (value == MouseCursor.Default)
{ {
cursor_handle = Functions.LoadCursor(CursorName.Arrow);
oldCursor = Functions.SetCursor(cursor_handle);
cursor = value; cursor = value;
cursor_handle = Functions.LoadCursor(CursorName.Arrow);
Functions.SetCursor(cursor_handle);
} }
else else
{ {
@ -1159,29 +1164,51 @@ namespace OpenTK.Platform.Windows
var bmpIcon = bmp.GetHicon(); var bmpIcon = bmp.GetHicon();
var success = Functions.GetIconInfo(bmpIcon, out iconInfo); var success = Functions.GetIconInfo(bmpIcon, out iconInfo);
if (success) try
{ {
if (!success)
{
throw new System.ComponentModel.Win32Exception();
}
iconInfo.xHotspot = value.X; iconInfo.xHotspot = value.X;
iconInfo.yHotspot = value.Y; iconInfo.yHotspot = value.Y;
iconInfo.fIcon = false; iconInfo.fIcon = false;
var icon = Functions.CreateIconIndirect(ref iconInfo); var icon = Functions.CreateIconIndirect(ref iconInfo);
if (icon == IntPtr.Zero)
if (icon != IntPtr.Zero)
{ {
// Currently using a custom cursor so destroy it throw new System.ComponentModel.Win32Exception();
// once replaced
cursor = value;
cursor_handle = icon;
oldCursor = Functions.SetCursor(icon);
} }
// Need to destroy this icon when/if it's replaced by another cursor.
cursor = value;
cursor_handle = icon;
Functions.SetCursor(icon);
}
finally
{
if (success)
{
// GetIconInfo creates bitmaps for the hbmMask and hbmColor members of ICONINFO.
// The calling application must manage these bitmaps and delete them when they are no longer necessary.
Functions.DeleteObject(iconInfo.hbmColor);
Functions.DeleteObject(iconInfo.hbmMask);
}
Functions.DestroyIcon(bmpIcon);
} }
} }
} }
Debug.Assert(oldCursorHandle != IntPtr.Zero);
Debug.Assert(oldCursorHandle != cursor_handle);
Debug.Assert(oldCursor != cursor);
if (destoryOld && oldCursor != IntPtr.Zero) // If we've replaced a custom (non-default) cursor we need to free the handle.
if (oldCursor != MouseCursor.Default)
{ {
Functions.DestroyIcon(oldCursor); Functions.DestroyIcon(oldCursorHandle);
} }
} }
} }