2015-11-02 3 views
3

Я столкнулся с каким-то странным поведением, играя с пользовательскими курсорами в C#, используя Windows Forms. Я уменьшил проблему до нового проекта с 1 формой, 2 панели, добавленными в форму, 1 значок добавлен в свойства проекта/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 свойство формы. Я загрузил несколько случайных изображений из разных источников и установил их как фоновое изображение формы.

  • Когда я устанавливаю некоторые из них и запускаю программу, обе панели имеют свой собственный курсор.

  • Когда я устанавливаю другие изображения, только вторая панель имеет свой указатель.

  • Я даже нашел изображение, с которым панель1 имеет свой курсор в течение первых нескольких секунд, но если мне удастся выйти и вернуться в панель после этих нескольких секунд, курсор будет удален.

Если я изменяю свойство backgroundimagelayout формы на None вместо Tile, курсор работает независимо от того, что изображение.

Нет ничего другого, что было бы изменено во всем проекте. 1 форма, 2 панели, 1 значок в качестве курсора, 3 изображения и абсолютно бессмысленное (или, может быть, нет, может быть, я чего-то не так) поведение.

Я просто хочу узнать, что вызывает такое поведение, когда я столкнулся с ним, работая над большим проектом, и мне потребовалось некоторое время, чтобы отследить суть проблемы. Может быть, я не должен использовать курсоры таким образом, но остается вопрос: что делает C# таким образом, когда изменяется только фоновое изображение.

Я сделал образец проекта здесь - https://www.dropbox.com/s/bl4iomzyz1bv7kb/Sample.rar?dl=0

ответ

3

Из статьи MSDN для Icon.Handle собственности, которую вы используете:

Это не копия ручки; не освобождайте его.

Это немного более загадочно, чем могло бы быть, мягко говоря. Это означает, что дескриптор действителен только до тех пор, пока объект Icon не будет уничтожен. Это проблема в вашем коде, вы не уверены, что объект new, возвращаемый 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); 
    } 

FWIW, довольно безопасно предположить, что если Microsoft может проектировали .NET 1.0 иконок и курсоров классов снова и снова, и объект Properties.Resources, они, вероятно, сделали бы это по-другому :)

Смежные вопросы