When reading a Cursor from a resources file an ArgumentException is thrown

Viewed 5432

When I use a MemoryStream to load a Cursor from a resources file I receive an ArgumentException. Here is the code I use to load the cursor:

Cursor myCursor
    = new Cursor(new MemoryStream(WaterforMGC.Properties.Resources.waterspray));
Cursor = myCursor;

But I get the error. I have no idea what is wrong, I even changed Cursor = myCursor; to this.Cursor = myCursor; which gave me the same error. I tried gameform.Cursor = myCursor; but that didn't work at all.

System.ArgumentException: Image format is not valid. The image file may be corrupted.
Parameter name: stream ---> System.Runtime.InteropServices.COMException (0x800A01E1): Exception from HRESULT: 0x800A01E1 (CTL_E_INVALIDPICTURE)
   at System.Windows.Forms.UnsafeNativeMethods.IPersistStream.Load(IStream pstm)
   at System.Windows.Forms.Cursor.LoadPicture(IStream stream)
   --- End of inner exception stack trace ---
   at System.Windows.Forms.Cursor.LoadPicture(IStream stream)
   at WaterforMGC.gameform.Form1_Load(Object sender, EventArgs e) in C:\Users\Jan\Documents\Visual Studio 2008\Projects\WaterforMGC\WaterforMGC\Form1.cs:line 39
   at System.Windows.Forms.Form.OnLoad(EventArgs e)
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.Control.CreateControl()
   at System.Windows.Forms.Control.WmShowWindow(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
4 Answers

In fact you can load colored cursors into .Net. You just need to use win32 do it.

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType, int cxDesired, int cyDesired, uint fuLoad);

//........

const int IMAGE_CURSOR = 2; 
const uint LR_LOADFROMFILE = 0x00000010;
IntPtr ipImage = LoadImage(IntPtr.Zero, 
    @"c:\mycolor.cur", 
    IMAGE_CURSOR, 
    0, 
    0, 
    LR_LOADFROMFILE);

Cursor testCursor = new Cursor(ipImage);

Cursor.Current = testCursor;

Because you have your cursor as a resource of the project, you could do this:

[DllImport("User32.dll", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern IntPtr LoadCursorFromFile(String str);

public static Cursor LoadCursorFromResource(Icon icono)  // Assuming that the resource is an Icon, but also could be a Image or a Bitmap
{
    // Saving cursor icon in temp file, necessary for loading through Win API
    string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".cur";
    using (var fileStream = File.Open(fileName, FileMode.Create))
    {
        icono.Save(fileStream);
    }

    // Loading cursor from temp file, using Win API
    Cursor result = new Cursor(LoadCursorFromFile(fileName));

    // Deleting temp file
    File.Delete(fileName);

    return result;
}

Then, for getting the cursor, you just do:

Cursor myCursor = LoadCursorFromResource(WaterforMGC.Properties.Resources.waterspray);

Reading the cursor from a file through a pointer using Win API allows you to handle animated or color cursors, despite the limitations listed in MSDN for the Cursor class.

My answer was based on this another SO answer (and happily tested on .NET 4.0).

Related