从资源文件中读取Cursor时,抛出ArgumentException

时间:2011-07-12 17:07:15

标签: c# .net winforms

当我使用MemoryStream从资源文件加载Cursor时,我会收到ArgumentException。这是我用来加载光标的代码:

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

但是我得到了错误。我不知道出了什么问题,我甚至将Cursor = myCursor;更改为this.Cursor = myCursor;,这给了我同样的错误。我试过了gameform.Cursor = myCursor;,但这根本不起作用。

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 个答案:

答案 0 :(得分:11)

问题在异常的第一行详细说明:

  

System.ArgumentException:图像格式无效。图像文件   可能已被破坏。

您确定要加载的图片处于未损坏的状态,并且是compatible with the image format for cursors?

  

Cursor类不支持动画光标(.ani文件)或光标不是黑白色

你还有其他加载光标图像的地方吗?你可能能够解决这个问题,以确定这里出了什么问题。

答案 1 :(得分:6)

实际上你可以将彩色光标加载到.Net中。你只需要使用win32就可以了。

[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;

答案 2 :(得分:3)

由于某种原因,游标类对它将读取的内容过于挑剔。您可以使用Windows API自己创建句柄,然后将其传递给游标类。

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

答案 3 :(得分:0)

因为您将光标作为项目的资源,所以可以这样做:

[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;
}

然后,为了获得光标,你只需:

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

使用Win API通过指针从文件中读取光标可以处理动画或彩色光标,尽管MSDN中列出了Cursor类的限制。

我的回答是基于this another SO answer(并且在.NET 4.0上进行了愉快的测试)。