9

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)
6
  • What image format is your image in? Commented Jul 12, 2011 at 17:10
  • exception messages are there to be read... Obviously you haven't done that, because you changed stuff in the line after that one that resulted in the exception to fix the error... Commented Jul 12, 2011 at 17:11
  • @Dan: I doubt he knew what he was looking for in that giant wall of exception text. I pared it down, hopefully it will help. Commented Jul 12, 2011 at 17:12
  • @sixlettervariables: I did the same a few seconds ago. Looks like you overwrote my changes ;) Commented Jul 12, 2011 at 17:12
  • 2
    @six That was a nice edit. (Imaginary) Editing +1! Commented Jul 12, 2011 at 17:13

4 Answers 4

11

The problem is spelled out on the very first line of the exception:

System.ArgumentException: Image format is not valid. The image file may be corrupted.

Are you sure the image you're loading is in an uncorrupted state, and is compatible with the image format for cursors?

The Cursor class does not support animated cursors (.ani files) or cursors with colors other than black and white.

Do you have any other places where you load a cursor image and it works? You might be able to work off of that to determine what's going wrong here.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, I'm sure. I'm using a .cur file for my cursor. I have no idea what's wrong... And I've never loaded a cursor in C#
@janj: per MSDN, "The Cursor class does not support animated cursors (.ani files) or cursors with colors other than black and white." Are they animated or colored?
...cursors with colors other than black and white. Damn it. Is there anything I can do about this? Edit: I saw meissnersd's post below. Don't worry!
There must be another way... It must be possible, after all Windows allows you to change your cursor!
7

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;

1 Comment

How can I do that from a memory stream? The stream comes from assembly.GetManifestResourceStream(...
3

For some reason the cursor class is far too picky about what it will read. You can create the handle yourself using the windows API then pass that to the cursor class.

C#:

//(in a class)
public static Cursor ActuallyLoadCursor(String path) {
    return new Cursor(LoadCursorFromFile(path))
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr LoadCursorFromFile(string fileName);

VB.Net:

'(in a class)'
Public Shared Function ActuallyLoadCursor(path As String) As Cursor
    Return New Cursor(LoadCursorFromFile(path))
End Function
<System.Runtime.InteropServices.DllImport("user32.dll")>
Private Shared Function LoadCursorFromFile(fileName As String) As IntPtr
End Function

Comments

0

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.