自定义光标异常?

时间:2015-11-02 22:51:11

标签: c# image winforms cursor panel

使用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

1 个答案:

答案 0 :(得分:3)

从您使用的Icon.Handle属性的MSDN文章:

  

这不是句柄的副本;不要释放它。

说得温和一点,这比它可能有点神秘。它的意思是只要Icon对象没有被销毁,Handle才有效。这是您的代码中的问题,您无法确保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,非常安全地假设如果微软可以再次设计.NET 1.0 Icon和Cursor类,以及Properties.Resources工具,他们可能会以不同的方式完成它:)