我在使用 Windows 窗体在 C# 中使用自定义游标时遇到了一些奇怪的行为。我已将问题减少到一个新项目,其中包含 1 个表单、2 个面板添加到表单、1 个图标添加到项目的 properties/resources.resx,以及 3 个图像添加到同一个地方。
项目唯一的代码就是这个
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TestProject
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
panel1.Cursor = new Cursor(Properties.Resources.randomIcon.Handle);
panel2.Cursor = new Cursor(Properties.Resources.randomIcon.Handle);
}
}
}
现在,当我修改 Form 的 backgroundimage 属性时,奇怪的行为开始了。我从各种来源下载了多个随机图像并将它们设置为表单的背景图像。
当我设置其中一些并运行程序时,两个面板都有自己的自定义光标。
当我设置其他图像时,只有第二个面板有光标。
我什至找到了一张图片,其中 panel1 在前几秒有光标,但如果我碰巧在那几秒后离开并返回面板,光标将被永久删除。
如果我将表单的 backgroundimagelayout 属性更改为 None 而不是 Tile,则无论图像是什么,光标都会起作用。
整个项目中没有任何其他内容需要修改。 1 个表格、2 个面板、1 个作为光标的图标、3 张图像和完全没有意义的(或者可能没有,也许我遗漏了什么)行为。
我只是想找出导致这种行为的原因,因为我在处理更大的项目时遇到了这种情况,我花了一些时间来追踪问题的核心。也许我不应该以这种方式使用游标,但问题仍然存在,是什么让 c# 在仅修改背景图像时以这种方式运行。
我在这里做了一个示例项目 - https://www.dropbox.com/s/bl4iomzyz1bv7kb/Sample.rar?dl=0
最佳答案
来自您使用的 Icon.Handle 属性的 MSDN 文章:
This is not a copy of the handle; do not free it.
委婉地说,这比实际情况更隐秘。它的意思是 Handle 仅在 Icon 对象未被销毁时才有效。这是您的代码中的一个问题,您没有确保 Properties.Resources.randomIcon 返回的 new 对象在任何地方都被引用。
所以垃圾收集器一运行,图标对象就成为历史。句柄不再有效。这反过来又使游标无效。图像的唯一相关性是它们对 GC 的影响。
你必须这样写:
private Icon customCursor;
public Form1()
{
InitializeComponent();
customCursor = Properties.Resources.Cat;
panel1.Cursor = panel2.Cursor = new Cursor(customCursor.Handle);
}
现在,只要表单对象保持事件状态,垃圾收集器就会始终看到对 Icon 对象的引用。所以它的 Handle 属性保持有效。
这也有勋章的另一面。 Icon 类实现 IDisposable。所以成为一个优秀的 .NET 公民:
protected override void OnFormClosed(FormClosedEventArgs e) {
customCursor.Dispose();
base.OnFormClosed(e);
}
Fwiw,可以很安全地假设,如果 Microsoft 可以重新设计 .NET 1.0 图标和 Cursor 类,以及 Properties.Resources 工具,他们可能会采用不同的方式:)
关于c# - 自定义光标异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33488483/