在.NET中实现彩色、动态光标(colored cursor)

        在win32中实现彩色、动态光标是很easy的事情,只要光标文件是彩色的就可以了。在.NET里面实现起来就不是那么直接了,查阅MSDN发现.NET中的Cursor类不支持彩色或动态光标,原文是这样的 “Cursor 类不支持动画光标(.ani 文件),也不支持彩色(而非黑白色光标)”,这的确有点不爽。遇到这类问题,第一反应就是我们的老办法,先上网查查,看能不能找到解决方案。不负所望,在buidu,google上都能找到相关的文章,问题也得已解决。不过所看到页面的解释也不多,于是在此再次根大家一起讨论学习。
        好了,我们言归正传,完成一个彩色或动态光标,大约过程是这样的,使用user32.dll提供的LoadCursorFromFile(String fileName)函数得到一个Windows 句柄,把Windows句柄传给Cursor(IntPtr handle)构造函数,得到一个Cursor对象实例后,调用user32.dll提供的DestroyCursor将Windows句柄所占有的资源释放。具体例子见代码:
  
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;
using System.Reflection;

namespace CursorTest
{
    
/// <summary>
    
/// 定义一个Form1类型
    
/// </summary>

    public class Form1 : Form
    
{
        
/// <summary>
        
/// 导入user32.dll中的LoadCursorFromFile函数,用于加载光标文件,并得到光标句柄
        
/// </summary>
        
/// <param name="fileName">光标文件的全名称</param>
        
/// <returns>光标句柄</returns>

        [DllImportAttribute("user32.dll")]
        
public static extern IntPtr LoadCursorFromFile(String fileName);

        
/// <summary>
        
/// 导入user32.dll中的DestroyCursor函数,用于销毁光标句柄,清除资源.
        
/// </summary>
        
/// <param name="cursorHandle">需要删除的光标句柄</param>
        
/// <returns></returns>

        [DllImportAttribute("user32.dll")]
        
public static extern uint DestroyCursor(IntPtr cursorHandle);

        
/// <summary>
        
/// 从光标库中随机得到一个关闭句柄
        
/// </summary>

        public IntPtr RandomCursorHandle
        
{
            
get
            
{
                String folder 
= @"K:\ani";
                String[] files 
= Directory.GetFiles(folder,"*.ani");//获取该目录下的所有的ani文件

                Random random 
= new Random();
                Int32 index 
= random.Next(0, files.Length);

                IntPtr handle 
= LoadCursorFromFile(files[index]);//根据随机生成的index加载一个光标文件
                return handle;//返回光标句柄
            }

        }


        
public static void Main()
        
{
            Form1 form 
= new Form1();
            form.Cursor 
= new Cursor(form.RandomCursorHandle);
            
//应用程序在空闲时会触发Appliction.Idle事件,这样可以看到光标不挺变化的效果,在不停变化时我们得留言光标句柄的资源释放
            Application.Idle += new EventHandler(form.OnApplicationIdle);
            Application.Run(form);
        }


        
private void OnApplicationIdle(Object sender, EventArgs e)
        
{
            IntPtr handle 
= this.RandomCursorHandle;
            
//在该Cursor(handle)函数中,MSDN中有这么一句话“处理完光标句柄后必须将其释放”
            
//因此,我们在构造完Cursor对象后,将handle释放。
            this.Cursor = new Cursor(handle);
            
            
//若不释放在运行过程中,通过任务管理器,发现改程序进程所占有的GDI对象数一直上升,到大9999后,程序将无法运行。
            DestroyCursor(handle);

            
//比较奇怪的是,下面这个语句返回的是true,按照DestroyCursor的意思是销毁该光标句柄所使用的资源,
            
//但是执行完DestoryCursor后光标还能够正常显示?
            System.Console.WriteLine(this.Cursor.Handle == handle);
        }


      
    }

}

   
posted on 2007-08-04 20:51  海楠  阅读(689)  评论(0编辑  收藏  举报