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");
但它没有工作…(当然):)
如何使用资源对象更改当前游标?
我通过将光标.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);