2015-11-02 99 views
3

我遇到了一些奇怪的行为,而使用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); 
     } 
    } 
} 

现在,当我修改窗体的BackgroundImage属性的怪异的行为开始。我从各种来源下载了多个随机图像,并将它们设置为表单的背景图像。

  • 当我设置其中一些并运行程序时,两个面板都有自定义光标。

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

  • 我甚至找到了一个图像,其中panel1的前几秒有光标,但如果在几秒钟之后我碰巧退出并返回面板,光标将被永久删除。

如果我改变了形式为无,而不是瓷砖的BackgroundImageLayout属性,光标作品无论形象是什么。

在整个项目中没有别的东西被修改。 1个窗体,2个面板,1个图标作为光标,3个图像和一个完全没有意义(或许不是,也许我错过了某些东西)的行为。

我只想找出导致此行为的原因,因为我在处理较大的项目时遇到了这种情况,而且我花了一段时间来跟踪问题的核心。也许我不应该用这种方式使用游标,但问题依然存在,只有当背景图像被修改时,c#才会以这种方式运行。

我做了一个在这里示例项目 - https://www.dropbox.com/s/bl4iomzyz1bv7kb/Sample.rar?dl=0

回答

3

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

这不是手柄的复印件;不要释放它。

这比它可能更隐蔽一点,说得温和。它的意思是只要Icon对象没有被销毁,Handle就是有效的。这是代码中的一个问题,您不确定Properties.Resources.randomIcon返回的对象是否在任何地方被引用。

所以只要垃圾收集器运行,图标对象就是历史。手柄不再有效。这反过来又使游标无效。图像的唯一相关性是它们对GC的影响。

你必须把它写这样代替:

private Icon customCursor; 

    public Form1() 
    { 
     InitializeComponent(); 
     customCursor = Properties.Resources.Cat; 
     panel1.Cursor = panel2.Cursor = new Cursor(customCursor.Handle); 
    } 

现在的垃圾收集器总是能看到该图标对象的引用,只要表单对象保持活着。所以它的Handle属性保持有效。

这也有另一面的奖章。 Icon类实现IDisposable。所以是一个很好的.NET公民:

protected override void OnFormClosed(FormClosedEventArgs e) { 
     customCursor.Dispose(); 
     base.OnFormClosed(e); 
    } 

FWIW,很安全的假设,如果微软能够设计.NET 1.0图标光标类一遍,和Properties.Resources设施,他们可能会做它不同:)