Assuming I have an existing System.Drawing.Bitmap
object, how do I create a System.Windows.Forms.Cursor
object with the same pixel data as my Bitmap
object?
Asked
Active
Viewed 3,745 times
1
-
*You also need to manually use the DesroyIcon() API to release the IntPtr retrieved with GetHicon(). – Idle_Mind Jun 14 '13 at 02:30
-
Thanks for the link, I'll give that solution a shot. It's not a duplicate question though, even though the answer is relevant; that question is very situation-specific, whereas this question is general to any situation where you might want to create a Cursor from a Bitmap. – Walt D Jun 14 '13 at 02:31
-
There's more to a cursor than just a bitmap. The hotspot and masks are not going to fall from the sky. – Hans Passant Jun 14 '13 at 03:11
-
As Hans points out, the "possible duplicate" solution linked to by Romoku is incomplete because it does not show how to set the hotspot. I have posted a better answer below. – Walt D Jun 14 '13 at 05:33
-
What question is this a "duplicate" of? Just because a question has the same answer as another question, that doesn't mean it's the same question. – Walt D Jun 14 '13 at 14:42
1 Answers
4
This answer is taken from this question. It allows you to both create a Cursor from a Bitmap object and set its hotspot.
public struct IconInfo
{
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
[DllImport("user32.dll")]
public static extern IntPtr CreateIconIndirect(ref IconInfo icon);
/// <summary>
/// Create a cursor from a bitmap without resizing and with the specified
/// hot spot
/// </summary>
public static Cursor CreateCursorNoResize(Bitmap bmp, int xHotSpot, int yHotSpot)
{
IntPtr ptr = bmp.GetHicon();
IconInfo tmp = new IconInfo();
GetIconInfo(ptr, ref tmp);
tmp.xHotspot = xHotSpot;
tmp.yHotspot = yHotSpot;
tmp.fIcon = false;
ptr = CreateIconIndirect(ref tmp);
return new Cursor(ptr);
}
/// <summary>
/// Create a 32x32 cursor from a bitmap, with the hot spot in the middle
/// </summary>
public static Cursor CreateCursor(Bitmap bmp)
{
int xHotSpot = 16;
int yHotSpot = 16;
IntPtr ptr = ((Bitmap)ResizeImage(bmp, 32, 32)).GetHicon();
IconInfo tmp = new IconInfo();
GetIconInfo(ptr, ref tmp);
tmp.xHotspot = xHotSpot;
tmp.yHotspot = yHotSpot;
tmp.fIcon = false;
ptr = CreateIconIndirect(ref tmp);
return new Cursor(ptr);
}
Edit: As pointed out in the comments, when a Cursor
is created from an IntPtr
handle, disposing the cursor will not release the handle itself, which will create a memory leak unless you release it yourself manually using the DestroyIcon
function:
[DllImport("user32.dll")]
private static extern bool DestroyIcon(IntPtr hIcon);
And then you can call the function like this:
DestroyIcon(myCursor.Handle);

Walt D
- 4,491
- 6
- 33
- 43
-
1Cursor created from IntPtr handle does not release the handle when it's disposed. It results in memory leak, unless use manually release Cursor.Handle. – Ondrej Petrzilka Sep 30 '16 at 07:56
-
1
-
It's not a good point, it's a critical point. Can you show an example of how you ended up successfully addressing this memory-leak issue? – Jazimov Nov 19 '18 at 15:23
-
-
Thanks. I've been working with this and now the problem becomes where exactly to carry out the DestroyIcon operation--do it too soon and the cursor won't show properly... – Jazimov Nov 19 '18 at 23:53