c#:如何从资源文件加载游标

本文关键字:源文件 加载 游标 资源 | 更新日期: 2023-09-27 18:04:03

我导入了一个文件"x.a I "到资源文件Resources.resx中。现在尝试使用ResourceManager.GetObject("aero_busy.ani")

加载该文件
Cursor.Current = (Cursor)ResourcesX.GetObject("aero_busy.ani");

但它没有工作…(当然):)

如何使用资源对象更改当前游标?

c#:如何从资源文件加载游标

我通过将光标.cur文件添加到项目的资源部分(我使用Visual Studio)来做到这一点。我不确定它是否必须是。cur,只要开发程序可以加载它。

在我的代码的变量声明部分,我从游标文件创建了一个MemoryStream:

private static System.IO.MemoryStream cursorMemoryStream = new System.IO.MemoryStream(myCurrentProject.Properties.Resources.myCursorFile);

…然后你可以从MemoryStream中创建游标:

private Cursor newCursor = new Cursor(cursorMemoryStream);

然后你可以在程序中随意分配游标,例如

pictureBox1.Cursor = newCursor;

和新的游标被编译为程序的一部分。

我还没有找到比转储到临时文件和使用Win32从文件加载游标方法更好的方法。hack是这样的(为了清晰起见,我删除了一大块样板代码,其中使用来自流的数据编写了一个临时文件)。此外,所有异常处理等被删除。

[DllImport("User32.dll", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
private static extern IntPtr LoadCursorFromFile(String str);
public static Cursor LoadCursorFromResource(string resourceName)
{         
     Stream cursorStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);        
     // Write a temp file here with the data in cursorStream
     Cursor result = new Cursor(LoadCursorFromFile(tempFile));
     File.Delete(tempFile);
     return result.
}

您可以将其用作(加载嵌入式资源时请记住名称空间)。

Cursors.Current = LoadCursorFromResource("My.Namespace.Filename");

经过几轮的问题,我发现优雅的解决方案是:

internal static Cursor GetCursor(string cursorName)
    {
        var buffer = Properties.Resources.ResourceManager.GetObject(cursorName) as byte[];
        using (var m = new MemoryStream(buffer))
        {
            return new Cursor(m);
        }
    }

我认为这个问题与光标必须具有。cur扩展名才能用作光标有关。

//下面的代码从一个嵌入的资源中生成一个游标。

//要添加自定义光标,请创建或使用现有的16 × 16位图// 1。在项目中添加一个新的游标文件://文件->添加新项->本地项目项->光标文件// 2。选择16x16图像类型://图像->当前图标图像类型->16x16

以上内容摘自MSDN。

更新:找到了答案。

"注意注意

Cursor类不支持动画游标。ANI文件)或使用非黑色和白色的游标。"

在这里找到

将文件写入磁盘然后将其作为游标导入是不切实际的,有一个更简单的解决方案。将。cur转换为。ico,并将光标作为图标资源导入。然后您可以简单地执行:

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

这将正确支持32位颜色

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

齐心协力…

这是Visual Studio现在提供的强类型资源的组合,加上Win32 LoadCursorFromFile(通过Anders使用manifest资源加载的原始答案)。

我还抛出了一个实例化游标的缓存,因为这适合我的应用程序。如果你不需要它,请删除它。

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

示例调用:

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