C#: How to load Cursor from Resource file?

Viewed 20510

I have imported a file "x.ani" into Resource file Resources.resx. Now trying to load that file using ResourceManager.GetObject("aero_busy.ani")

Cursor.Current = (Cursor)ResourcesX.GetObject("aero_busy.ani");

but it didn't work .. (certainly) :)

How can I change the current Cursor using resource object?

7 Answers

Writing a file to disk then importing it as a cursor is impractical, there is simpler solution. Convert your .cur to .ico and import your cursor as an icon resource. Then you can simply do:

Cursor c = new Cursor(Properties.Resources.mycursor.Handle);

This will support 32 bit colors properly.

    [DllImport("User32.dll")]
    private static extern IntPtr LoadCursorFromFile(string str);

    Cursor SetCursor(byte[] resourceName)
    {
        string tempPath = @"C:\Users\Public\Documents\temp.cur";
        File.WriteAllBytes(tempPath, resourceName);
        Cursor result = new Cursor(LoadCursorFromFile(tempPath));
        File.Delete(tempPath);
        return result;
    }

Pulling it all together...

This is a combination of the strongly typed resources Visual Studio now provides, plus Win32 LoadCursorFromFile (via Anders original answer using manifest resource loads).

I also threw in a cache of instantiated cursors, because that's appropriate for my app. Nuke that if you don't need it.

namespace Draw
{
/// <summary>
/// Controls use of all the cursors in the app, supports loading from strongly typed resources, and caches all references for the lifetime of the app.
/// </summary>
public static class Cursors
{
    // Cache of already loaded cursors
    private static ConcurrentDictionary<byte[], Cursor> cache = new ConcurrentDictionary<byte[], Cursor>();

    /// <summary>
    /// Returns a cursor given the appropriate id from Resources.Designer.cs (auto-generated from Resources.resx). All cursors are
    /// cached, so do not Dispose of the cursor returned from this function.
    /// </summary>
    /// <param name="cursorResource">The resource of the cursor to load. e.g. Properties.Resources.MyCursor (or byte array from .cur or .ani file)</param>
    /// <returns>The cursor. Do not Dispose this returned cursor as it is cached for the app's lifetime.</returns>
    public static Cursor GetCursor(byte[] cursorResource)
    {
        // Have we already loaded this cursor? Use that.
        if (cache.TryGetValue(cursorResource, out Cursor cursor))
            return cursor;

        // Get a temporary file
        var tmpFile = Utils.GetTempFile();

        try
        {
            // Write the cursor resource to temp file
            File.WriteAllBytes(tmpFile, cursorResource);

            // Read back in from temp file as a cursor. Unlike Cursor(MemoryStream(byte[])) constructor, 
            // the Cursor(Int32 handle) version deals correctly with all cursor types.
            cursor = new Cursor(Win32.LoadCursorFromFile(tmpFile));

            // Update dictionary and return
            cache.AddOrUpdate(cursorResource, cursor, (key, old) => cursor);
            return cursor;
        }
        finally
        {
            // Remove the temp file
            Utils.TryDeleteFile(tmpFile);
        }
    }
}
}

Example call:

Cursor = Draw.Cursors.GetCursor(Properties.Resources.Cursor_ArrowBoundary);
Related