4

I want to set a custom cursor within my WPF application. Originally I had a .png file, which i converted to .ico, but since I didn't find any way to set an .ico file as a cursor in WPF, I tried to do this with a proper .cur file.

I have created such an .cur file using Visual Studio 2013 (New Item -> Cursor File). The cursor is a coloured 24-bit image and its build-type is "Resource".

I accquire the resource stream with this:

var myCur = Application.GetResourceStream(new Uri("pack://application:,,,/mycur.cur")).Stream;

This code is able to retrieve the stream, so myCur is NOT null aferwards.

When trying to create the cursor with

var cursor = new System.Windows.Input.Cursor(myCur);

the default cursor Cursors.None is returned and not my custom cursor. So there seems to be a problem with that.

Can anybody tell me why the .ctor has problems with my cursor stream? The file was created using VS2013 itself, so I'd assume that the .cur file is correctly formatted. Alternatively: If someone knows how to load a .ico file as a cursor in WPF, I'd be very happy and very grateful.

EDIT: Just tried the same with a fresh new .cur file from VS2013 (8bpp) in case adding a new palette has screwed the image format. Same result. The .ctor of System.Windows.Input.Cursor can't even create a proper cursor from the 'fresh' cursor file.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
PuerNoctis
  • 1,364
  • 1
  • 15
  • 34

2 Answers2

3

Essentially you have to use the win32 method CreateIconIndirect

// FROM THE ABOVE LINK
public class CursorHelper
{
    private struct IconInfo
    {
        public bool fIcon;
        public int xHotspot;
        public int yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
    }

    [DllImport("user32.dll")]
    private static extern IntPtr CreateIconIndirect(ref IconInfo icon);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);


    public static Cursor CreateCursor(System.Drawing.Bitmap bmp, int xHotSpot, int yHotSpot)
    {
        IconInfo tmp = new IconInfo();
        GetIconInfo(bmp.GetHicon(), ref tmp);
        tmp.xHotspot = xHotSpot;
        tmp.yHotspot = yHotSpot;
        tmp.fIcon = false;

        IntPtr ptr = CreateIconIndirect(ref tmp);
        SafeFileHandle handle = new SafeFileHandle(ptr, true);
        return CursorInteropHelper.Create(handle);
    }
}
General Grievance
  • 4,555
  • 31
  • 31
  • 45
jt000
  • 3,196
  • 1
  • 18
  • 36
  • 1
    wrapping the result of CreateIconIndirect will result in an exception when the SafeFileHandle is GC'ed - see http://stackoverflow.com/questions/9218029/safefilehandle-close-throws-an-exception-but-the-handle-is-valid-and-works – user3391859 Oct 11 '16 at 17:12
3

This is exactly what I did and it seems to be working fine. I just added this to an "Images" folder under my project in Visual Studio 2013. Maybe it can't resolve your URI?

    Cursor paintBrush = new Cursor(
        Application.GetResourceStream(new Uri("Images/paintbrush.cur", UriKind.Relative)).Stream
        );

Sample cursor (worked for me): http://www.rw-designer.com/cursor-detail/67894

sciencectn
  • 1,405
  • 1
  • 16
  • 25