我使用类似于this question的接受答案的代码来制作自定义光标。我想我可以问,“当我完成自定义光标后我该怎么办?”但具体来说,我的问题分为两部分:
一:我看到使用反射来设置光标的“ownHandle”字段的代码。是否这样可以在放置Cursor对象时销毁(本机)句柄?如果不是它做了什么?
二:我是否必须手动处理光标对象或将新光标分配给控件导致控件为我配置光标? 例如:
private void customCursorButton_Clicked(object sender, EventArgs e)
{
this.Cursor = NativeMethods.LoadCustomCursor(@"c:\windows\cursors\aero_busy.ani");
}
private void defaultCursorButton_Clicked(object sender, EventArgs e)
{
var tmp = this.Cursor; // do I have to do this
this.Cursor = Cursors.Default;
tmp.Dispose(); // and this?
}
答案 0 :(得分:5)
如果您确定100%确定该对象未在其他任何地方使用,则您应该只对对象调用Dispose()。调用Dispose()是可选,对象的终结器确保清理将始终发生。并且100%确定它不会在其他任何地方使用。在完成这项工作时,这只是有点慢。
对于单个游标对象没什么意义,游标最多只有几千字节的内存。但是你的代码会为每次点击反复创建光标,并且有可能处理父光标(Cursor属性是一个环境属性),它不会赢得很多奖品。所以正确的代码应该像这样:
private Cursor CustomCursor;
private void customCursorButton_Clicked(object sender, EventArgs e)
{
if (CustomCursor == null) CustomCursor = NativeMethods.LoadCustomCursor(@"c:\windows\cursors\aero_busy.ani");
this.Cursor = CustomCursor;
}
private void defaultCursorButton_Clicked(object sender, EventArgs e)
{
var prev = this.Cursor;
this.Cursor = Cursors.Default;
if (prev == CustomCursor) {
CustomCursor.Dispose();
CustomCursor = null;
}
}
protected override OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
if (CustomCursor != null) CustomCursor.Dispose();
}
有一个简单的诊断可以知道你弄错了顺便说一下。任务管理器通常不适合分析.NET应用程序,但很高兴向您展示在这种情况下丢失Dispose()调用是否会让您遇到麻烦。使用View + Select Columns并勾选“GDI Objects”,它可以非常精确地跟踪光标对象(除了其他GDI对象)。让显示的值超过几百是一个麻烦的迹象,给予或接受。
请注意,必须使用Environment.GetFolderPath()来检索Windows的安装位置。处理失败,没有硬性保证光标始终可用。细节,细节。
答案 1 :(得分:1)
你应该处理你正在创建的对象,你的做法似乎很好。
请不要忘记在窗体关闭时处理自定义光标。
我看到使用反射来设置光标的“ownHandle”字段的代码。是否这样可以在放置Cursor对象时销毁(本机)句柄?如果不是它做了什么?
它应该释放手柄。处置设计以释放非托管资源。
我是否必须手动处理光标对象或将新光标分配给控件导致控件为我配置光标?
丢失对包含非托管资源的对象的引用是个坏主意。它最终会被GC控制,并且会调用desctuctor,处理对象,但仍然。
重新分配属性Cursor
是另一回事。可能会创建属性的setter来自行处理旧值,但是,我强烈认为它不会这样做。