自定义光标异常?

3
我在使用Windows Forms的C#自定义光标时遇到了一些奇怪的行为。我将问题简化为一个新项目,其中包括1个窗体、2个添加到窗体的面板、1个添加到项目属性/资源.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);
        }
    }
}

现在问题出现在我修改了窗体的背景图像属性时。我从各种来源下载了多个随机图像,并将它们设置为表单的背景图像。
  • 当我设置其中一些并运行程序时,两个面板都有自定义光标。

  • 当我设置其他图像时,只有第二个面板有自定义光标。

  • 我甚至找到了一张图片,面板1在前几秒钟内拥有它的光标,但如果我在这几秒钟后离开并重新进入该面板,则光标会永久删除。

如果我将窗体的背景图像布局属性更改为"None"而不是"Tile",则无论图像如何,光标都可以使用。

整个项目中没有进行任何其他修改。1个表单、2个面板、1个图标作为光标、3个图像和完全没有意义的(或者可能不是,也许我错过了什么)行为。

我只想弄清楚是什么原因导致了这种行为,因为我遇到了这个问题,而我正在处理一个更大的项目,追踪问题的核心花费了我一段时间。也许我不应该用这种方式使用光标,但问题仍然存在,为什么C#在除背景图像之外没有进行任何修改时会出现这种行为。

我制作了一个示例项目,下载链接: https://www.dropbox.com/s/bl4iomzyz1bv7kb/Sample.rar?dl=0

1个回答

3
从使用Icon.Handle属性的MSDN文章中可以得知:
此处不是句柄的复制,不要释放它。
这个说法可能有点晦涩难懂。实际上,它的意思是只有在Icon对象没有被销毁的情况下,Handle才是有效的。如果你的代码存在问题,即没有确保由Properties.Resources.randomIcon返回的新对象被引用到任何地方。
因此,一旦垃圾回收器运行,图标对象就会消失。而且句柄也将不再有效。这反过来又使光标无效。图像的唯一相关性就是它们对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);
    }

值得一提的是,如果微软有机会重新设计.NET 1.0的图标和光标类以及Properties.Resources功能,他们可能会做出不同的设计 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接