Click here to Skip to main content
15,891,981 members
Articles / Programming Languages / C#

Extended Cursors for .Net

Rate me:
Please Sign up or sign in to vote.
4.83/5 (25 votes)
2 Feb 2009CPOL13 min read 51.4K   2.8K   69  
A design-time component to make use of animated/multi-coloured cursors
using System;
using System.Collections;
using System.ComponentModel;
using System.Resources;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using ExtCursors.Design;

namespace ExtCursors
{
    #region "Internal enumerators"
    internal enum _DesignLoadCursorFrom
    {
        LocalResource,
        ResxResource,
        File,
        None,
        RuntimeCreated,
        RuntimeCreatedResxResource,
        FromImage
    }
    #endregion //"Internal enumerators"

    #region "Class : ExtCursor"
    // ========================================================================
	// ========================================================================
    /// <summary>
    /// An extended cursor class that can load animated and multi-coloured cursors.
    /// </summary>
    [ToolboxItem(true)]
    [DesignTimeVisible(true)]
    [ToolboxBitmap(typeof(ExtCursor), "Images.ExtCursor.bmp")]
	[ToolboxItemFilter("System.Windows.Forms")]
    [DefaultProperty("CursorFile")]
    public class ExtCursor : Component, ISupportInitialize
    {
        #region "Private/Internal fields"
        #region "Private fields - disposal"
        private bool _Disposed = false;
        #endregion //"Private fields - disposal"
        #region "Private fields - ISupportInitialize flags"
        internal bool _Initializing = false;
        #endregion //"Private fields - ISupportInitialize flags"
        internal MemoryStream _CursorStream = null;
        internal Cursor _Cursor = null;
        internal _DesignLoadCursorFrom _LoadFrom;
        private IntPtr _HCursor = IntPtr.Zero;
        private string _Filename = "";
		private string _CursorLocation = "";
		private bool _CursorFileLocal = false;
        internal string _ResourceName = "";
        internal string _ResXName = "";
        private bool _SharedHandle = false;
        private bool _OwnedHandle = false;
        private Size _PreferredSize = new Size(0, 0);
        private bool _DefaultSize = true;
        #endregion //"Private/Internal fields"
        #region "Event delegate keys"
        internal static readonly object EventHandleCreated = new object();
        internal static readonly object EventHandleDestroyed = new object();
        #endregion //"Event delegate keys"
        #region "User32/GDI/ComCtl32 Interop"
        [DllImport("user32.dll", EntryPoint = "DestroyCursor", CharSet = CharSet.Auto)]
        internal static extern bool DestroyCursor(IntPtr hCursor);
        [DllImport("user32.dll", EntryPoint = "LoadImage", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
        internal static extern IntPtr LoadImage(IntPtr hinst, string stName, int nType, int cxDesired, int cyDesired, int nFlags);
        [DllImport("user32.dll", EntryPoint = "CreateIconIndirect", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CreateIconIndirect([In, MarshalAs(UnmanagedType.LPStruct)]ExtCursor.ICONINFO iconInfo);
        [DllImport("comctl32.dll", EntryPoint = "ImageList_Draw", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
        public static extern bool ImageList_Draw(IntPtr himl, int i, IntPtr hdcDst, int x, int y, int fStyle);

        internal const int ILD_MASK = 0x0010;
        internal const int LR_DEFAULTCOLOR = 0x0000;
        //internal const int LR_MONOCHROME = 0x0001;
        //internal const int LR_COLOR = 0x0002;
        //internal const int LR_COPYRETURNORG = 0x0004;
        //internal const int LR_COPYDELETEORG = 0x0008;
        internal const int LR_LOADFROMFILE = 0x0010;
        //internal const int LR_LOADTRANSPARENT = 0x0020;
        internal const int LR_DEFAULTSIZE = 0x0040;
        //internal const int LR_VGACOLOR = 0x0080;
        //internal const int LR_LOADMAP3DCOLORS = 0x1000;
        //internal const int LR_CREATEDIBSECTION = 0x2000;
        //internal const int LR_COPYFROMRESOURCE = 0x4000;
        //internal const int LR_SHARED = unchecked((int)0x8000);
        internal const int IMAGE_CURSOR = 2;
        [StructLayout(LayoutKind.Sequential)]
        internal class ICONINFO
        {
            public int fIcon;
            public int xHotspot;
            public int yHotspot;
            public IntPtr hbmMask;
            public IntPtr hbmColor;
        }
        [DllImport("gdi32.dll")]
        private static extern bool DeleteObject(IntPtr hObject);
        #endregion //"User32/GDI/ComCtl32 Interop"

        #region "Constructors"
        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class.
        /// [for design time only]
        /// </summary>
        public ExtCursor()
		{
            _LoadFrom = _DesignLoadCursorFrom.None;
		}

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified bitmap image and mask.
        /// </summary>
        /// <param name="pCursorImage">Bitmap to use as the cursor.</param>
        /// <param name="pCursorMaskImage">Bitmap to use as the cursor mask.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        public ExtCursor(Bitmap pCursorImage, Bitmap pCursorMaskImage, Point pHotSpot)
        {
            this._LoadFrom = _DesignLoadCursorFrom.None;
            ConstructFromImage(pCursorImage, pCursorMaskImage, pHotSpot);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified bitmap image.
        /// (The transparent color is taken as the color of the bottom-left pixel)
        /// </summary>
        /// <param name="pCursorImage">Bitmap to use as the cursor.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        public ExtCursor(Bitmap pCursorImage, Point pHotSpot)
        {
            this._LoadFrom = _DesignLoadCursorFrom.FromImage;
            Color TransparentColor = pCursorImage.GetPixel(0, pCursorImage.Height - 1);
            Bitmap[] Bmps = CreateImageAndMask(pCursorImage, TransparentColor, false);
            Bitmap CursorBmp = Bmps[0];
            Bitmap MaskBmp = Bmps[1];
            try
            {
                ConstructFromImage(CursorBmp, MaskBmp, pHotSpot);
            }
            finally
            {
                if (CursorBmp != null)
                {
                    CursorBmp.Dispose();
                }
                if (MaskBmp != null)
                {
                    MaskBmp.Dispose();
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified bitmap image.
        /// (Optionally automatically drawing the cross-hairs for the cursor)
        /// (The transparent color is taken as the color of the bottom-left pixel)
        /// </summary>
        /// <param name="pCursorImage">Bitmap to use as the cursor.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        /// <param name="pWithCrossHairs">Flag determining whether cross-hairs should be added.</param>
        public ExtCursor(Bitmap pCursorImage, Point pHotSpot, bool pWithCrossHairs)
        {
            this._LoadFrom = _DesignLoadCursorFrom.FromImage;
            Color TransparentColor = pCursorImage.GetPixel(0, pCursorImage.Height - 1);
            Bitmap[] Bmps = CreateImageAndMask(pCursorImage, TransparentColor, pWithCrossHairs);
            Bitmap CursorBmp = Bmps[0];
            Bitmap MaskBmp = Bmps[1];
            try
            {
                ConstructFromImage(CursorBmp, MaskBmp, pHotSpot);
            }
            finally
            {
                if (CursorBmp != null)
                {
                    CursorBmp.Dispose();
                }
                if (MaskBmp != null)
                {
                    MaskBmp.Dispose();
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified bitmap image.
        /// </summary>
        /// <param name="pCursorImage">Bitmap to use as the cursor.</param>
        /// <param name="pTransparentColor">Transparent color of the cursor image.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        public ExtCursor(Bitmap pCursorImage, Color pTransparentColor, Point pHotSpot)
        {
            this._LoadFrom = _DesignLoadCursorFrom.FromImage;
            Bitmap[] Bmps = CreateImageAndMask(pCursorImage, pTransparentColor, false);
            Bitmap CursorBmp = Bmps[0];
            Bitmap MaskBmp = Bmps[1];
            try
            {
                ConstructFromImage(CursorBmp, MaskBmp, pHotSpot);
            }
            finally
            {
                if (CursorBmp != null)
                {
                    CursorBmp.Dispose();
                }
                if (MaskBmp != null)
                {
                    MaskBmp.Dispose();
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified bitmap image.
        /// (Optionally automatically drawing the cross-hairs for the cursor)
        /// </summary>
        /// <param name="pCursorImage">Bitmap to use as the cursor.</param>
        /// <param name="pTransparentColor">Transparent color of the cursor image.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        /// <param name="pWithCrossHairs">Flag determining whether cross-hairs should be added.</param>
        public ExtCursor(Bitmap pCursorImage, Color pTransparentColor, Point pHotSpot, bool pWithCrossHairs)
        {
            this._LoadFrom = _DesignLoadCursorFrom.FromImage;
            Bitmap[] Bmps = CreateImageAndMask(pCursorImage, pTransparentColor, pWithCrossHairs);
            Bitmap CursorBmp = Bmps[0];
            Bitmap MaskBmp = Bmps[1];
            try
            {
                ConstructFromImage(CursorBmp, MaskBmp, pHotSpot);
            }
            finally
            {
                if (CursorBmp != null)
                {
                    CursorBmp.Dispose();
                }
                if (MaskBmp != null)
                {
                    MaskBmp.Dispose();
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified image in an ImageList.
        /// </summary>
        /// <param name="pImageList">ImageList containing the cursor image.</param>
        /// <param name="pImageIndex">Index of the cursor image in the ImageList.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        public ExtCursor(ImageList pImageList, int pImageIndex, Point pHotSpot)
        {
            this._LoadFrom = _DesignLoadCursorFrom.FromImage;
            ConstructFromImageList(pImageList, pImageIndex, pHotSpot, false);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified image in an ImageList.
        /// (Optionally automatically drawing the cross-hairs for the cursor)
        /// </summary>
        /// <param name="pImageList">ImageList containing the cursor image.</param>
        /// <param name="pImageIndex">Index of the cursor image in the ImageList.</param>
        /// <param name="pHotSpot">HotSpot for the cursor.</param>
        /// <param name="pWithCrossHairs">Flag determining whether cross-hairs should be added.</param>
        public ExtCursor(ImageList pImageList, int pImageIndex, Point pHotSpot, bool pWithCrossHairs)
        {
            this._LoadFrom = _DesignLoadCursorFrom.FromImage;
            ConstructFromImageList(pImageList, pImageIndex, pHotSpot, pWithCrossHairs);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified file.
        /// </summary>
        /// <param name="pFilename">The cursor file to load.</param>
        public ExtCursor(string pFilename)
            : this(pFilename, true)
        {
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified file.
        /// </summary>
        /// <param name="pFilename">The cursor file to load.</param>
        /// <param name="pShareable">Whether the cursor handle is to be shared.</param>
        public ExtCursor(string pFilename, bool pShareable)
        {
            _LoadFrom = _DesignLoadCursorFrom.File;
            bool Loaded = false;
            if (pShareable)
            {
                _SharedHandle = true;
                _CursorLocation = pFilename;
                Loaded = ExtCursorsSharedRepository.Instance.AssignSharedHandle(this, _DefaultSize, _PreferredSize, null);
            }
            if (!Loaded)
            {
                _SharedHandle = false;
                FileStream LoadStream = null;
                try
                {
                    LoadStream = new FileStream(pFilename, FileMode.Open, FileAccess.Read);
                    LoadFromStream(LoadStream);
                }
                finally
                {
                    if (LoadStream != null)
                    {
                        LoadStream.Dispose();
                    }
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the supplied byte data.
        /// </summary>
        /// <param name="pCursorData">The byte data to load the cursor from.</param>
        public ExtCursor(byte[] pCursorData)
        {
            _LoadFrom = _DesignLoadCursorFrom.RuntimeCreated;
            LoadFromStream(pCursorData);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the supplied stream.
        /// </summary>
        /// <param name="pCursorStream">The stream to load the cursor from.</param>
        public ExtCursor(Stream pCursorStream)
        {
            _LoadFrom = _DesignLoadCursorFrom.RuntimeCreated;
            LoadFromStream(pCursorStream);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from a resource.
        /// </summary>
        /// <param name="pResourceAssembly">The assembly containing the resource.</param>
        /// <param name="pResXName">The name of the compiled resource file, e.g. "MyApp.Properties.Resources".</param>
        /// <param name="pResourceName">The name of the resource.</param>
        public ExtCursor(Assembly pResourceAssembly, string pResXName, string pResourceName)
            : this(pResourceAssembly, pResXName, pResourceName, true)
        {
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from a resource.
        /// </summary>
        /// <param name="pResourceAssembly">The assembly containing the resource.</param>
        /// <param name="pResXName">The name of the compiled resource file, e.g. "MyApp.Properties.Resources".</param>
        /// <param name="pResourceName">The name of the resource.</param>
        /// <param name="pShareable">Whether the cursor handle is to be shared.</param>
        public ExtCursor(Assembly pResourceAssembly, string pResXName, string pResourceName, bool pShareable)
        {
            _LoadFrom = _DesignLoadCursorFrom.RuntimeCreatedResxResource;
            bool Loaded = false;
            if (pShareable)
            {
                _SharedHandle = true;
                _ResXName = pResXName;
                _ResourceName = pResourceName;
                Loaded = ExtCursorsSharedRepository.Instance.AssignSharedHandle(this, _DefaultSize, _PreferredSize, pResourceAssembly);
            }
            if (!Loaded)
            {
                ResourceManager ResX = new ResourceManager(pResXName, pResourceAssembly);
                byte[] CursorData = (byte[])ResX.GetObject(pResourceName, null);
                LoadFromStream(CursorData);
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified file.
        /// </summary>
        /// <param name="pFilename">The cursor file to load.</param>
        /// <param name="pDefaultSize">Whether the default system metric cursor size should be used.</param>
        /// <param name="pPreferredSize">The preferred size of the cursor to load.</param>
        public ExtCursor(string pFilename, bool pDefaultSize, Size pPreferredSize)
            : this(pFilename, pDefaultSize, pPreferredSize, true)
        {
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the specified file.
        /// </summary>
        /// <param name="pFilename">The cursor file to load.</param>
        /// <param name="pDefaultSize">Whether the default system metric cursor size should be used.</param>
        /// <param name="pPreferredSize">The preferred size of the cursor to load.</param>
        /// <param name="pShareable">Whether the cursor handle is to be shared.</param>
        public ExtCursor(string pFilename, bool pDefaultSize, Size pPreferredSize, bool pShareable)
        {
            _LoadFrom = _DesignLoadCursorFrom.File;
            bool Loaded = false;
            if (pShareable)
            {
                _CursorLocation = pFilename;
                _SharedHandle = true;
                _DefaultSize = pDefaultSize;
                _PreferredSize = new Size(pPreferredSize.Width, pPreferredSize.Height);
                Loaded = ExtCursorsSharedRepository.Instance.AssignSharedHandle(this, _DefaultSize, _PreferredSize, null);
            }
            if (!Loaded)
            {
                _SharedHandle = false;
                LoadFromFileEx(pFilename, pDefaultSize, pPreferredSize);
            }
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the supplied byte data.
        /// </summary>
        /// <param name="pCursorData">The byte data to load the cursor from.</param>
        /// <param name="pDefaultSize">Whether the default system metric cursor size should be used.</param>
        /// <param name="pPreferredSize">The preferred size of the cursor to load.</param>
        public ExtCursor(byte[] pCursorData, bool pDefaultSize, Size pPreferredSize)
        {
            _LoadFrom = _DesignLoadCursorFrom.RuntimeCreated;
            LoadFromStreamEx(pCursorData, pDefaultSize, pPreferredSize);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from the supplied stream.
        /// </summary>
        /// <param name="pCursorStream">The stream to load the cursor from.</param>
        /// <param name="pDefaultSize">Whether the default system metric cursor size should be used.</param>
        /// <param name="pPreferredSize">The preferred size of the cursor to load.</param>
        public ExtCursor(Stream pCursorStream, bool pDefaultSize, Size pPreferredSize)
        {
            _LoadFrom = _DesignLoadCursorFrom.RuntimeCreated;
            LoadFromStreamEx(pCursorStream, pDefaultSize, pPreferredSize);
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from a resource.
        /// </summary>
        /// <param name="pResourceAssembly">The assembly containing the resource.</param>
        /// <param name="pResXName">The name of the compiled resource file, e.g. "MyApp.Properties.Resources".</param>
        /// <param name="pResourceName">The name of the resource.</param>
        /// <param name="pDefaultSize">Whether the default system metric cursor size should be used.</param>
        /// <param name="pPreferredSize">The preferred size of the cursor to load.</param>
        public ExtCursor(Assembly pResourceAssembly, string pResXName, string pResourceName, bool pDefaultSize, Size pPreferredSize)
            : this(pResourceAssembly, pResXName, pResourceName, pDefaultSize, pPreferredSize, true)
        {
        }

        // ========================================================================
        /// <summary>
        /// Initializes a new instance of the ExtCursor class from a resource.
        /// </summary>
        /// <param name="pResourceAssembly">The assembly containing the resource.</param>
        /// <param name="pResXName">The name of the compiled resource file, e.g. "MyApp.Properties.Resources".</param>
        /// <param name="pResourceName">The name of the resource.</param>
        /// <param name="pDefaultSize">Whether the default system metric cursor size should be used.</param>
        /// <param name="pPreferredSize">The preferred size of the cursor to load.</param>
        /// <param name="pShareable">Whether the cursor handle is to be shared.</param>
        public ExtCursor(Assembly pResourceAssembly, string pResXName, string pResourceName, bool pDefaultSize, Size pPreferredSize, bool pShareable)
        {
            _LoadFrom = _DesignLoadCursorFrom.RuntimeCreatedResxResource;
            bool Loaded = false;
            if (pShareable)
            {
                _SharedHandle = true;
                _ResXName = pResXName;
                _ResourceName = pResourceName;
                _DefaultSize = pDefaultSize;
                _PreferredSize = new Size(pPreferredSize.Width, pPreferredSize.Height);
                Loaded = ExtCursorsSharedRepository.Instance.AssignSharedHandle(this, _DefaultSize, _PreferredSize, pResourceAssembly);
            }
            if (!Loaded)
            {
                ResourceManager ResX = new ResourceManager(pResXName, pResourceAssembly);
                byte[] CursorData = (byte[])ResX.GetObject(pResourceName, null);
                LoadFromStreamEx(CursorData, pDefaultSize, pPreferredSize);
            }
        }
        #endregion //"Constructors"

        #region "Construct from image methods"
        // ========================================================================
        private void ConstructFromImageList(ImageList pImageList, int pImageIndex, Point pHotSpot, bool pWithCrossHairs)
        {
            IntPtr hMask = IntPtr.Zero;
            IntPtr hImage = IntPtr.Zero;
            Bitmap CursorBmp = null;
            Bitmap MaskBmp = null;
            Graphics Gfx = null;
            if (pWithCrossHairs)
            {
                ImageList TempImgList = null;
                Brush FillBrush = null;
                try
                {
                    // another imagelist is used to contain the cursor drawing with the cross-hairs...
                    TempImgList = new ImageList();
                    TempImgList.TransparentColor = Color.Transparent;
                    TempImgList.ImageSize = new Size(pImageList.ImageSize.Width * 2, pImageList.ImageSize.Height * 2);
                    CursorBmp = new Bitmap(pImageList.ImageSize.Width * 2, pImageList.ImageSize.Height * 2);
                    MaskBmp = new Bitmap(pImageList.ImageSize.Width * 2, pImageList.ImageSize.Height * 2);
                    Gfx = Graphics.FromImage(CursorBmp);
                    FillBrush = new SolidBrush(Color.Transparent);
                    Gfx.FillRectangle(FillBrush, 0, 0, pImageList.ImageSize.Width * 2, pImageList.ImageSize.Height * 2);
                    Gfx.DrawLine(SystemPens.WindowText, 5, 0, 5, 10);
                    Gfx.DrawLine(SystemPens.WindowText, 0, 5, 10, 5);
                    pImageList.Draw(Gfx, new Point(7, 7), pImageIndex);
                    Gfx.Dispose();
                    Gfx = null;
                    // add the cross-haired image to our temp image list...
                    TempImgList.Images.Add(CursorBmp, Color.Transparent);
                    // now draw the mask...
                    Gfx = Graphics.FromImage(MaskBmp);
                    IntPtr Hdc = Gfx.GetHdc();
                    ExtCursor.ImageList_Draw(TempImgList.Handle, 0, Hdc, 0, 0, ILD_MASK);
                    Gfx.ReleaseHdc(Hdc);
                    // get the bitmap handles...
                    hMask = MaskBmp.GetHbitmap();
                    hImage = CursorBmp.GetHbitmap();
                    // create the actual cursor...
                    ICONINFO IconInfo = new ICONINFO();
                    IconInfo.fIcon = 0;
                    IconInfo.xHotspot = 5;
                    IconInfo.yHotspot = 5;
                    IconInfo.hbmMask = hMask;
                    IconInfo.hbmColor = hImage;
                    AssignHCursor(CreateIconIndirect(IconInfo), true);
                }
                finally
                {
                    if (TempImgList != null)
                    {
                        TempImgList.Dispose();
                    }
                    if (Gfx != null)
                    {
                        Gfx.Dispose();
                    }
                    if (FillBrush != null)
                    {
                        FillBrush.Dispose();
                    }
                    if (CursorBmp != null)
                    {
                        CursorBmp.Dispose();
                    }
                    if (MaskBmp != null)
                    {
                        MaskBmp.Dispose();
                    }
                    if (hMask != IntPtr.Zero)
                    {
                        DeleteObject(hMask);
                    }
                    if (hImage != IntPtr.Zero)
                    {
                        DeleteObject(hImage);
                    }
                }
            }
            else
            {
                try
                {
                    MaskBmp = new Bitmap(pImageList.ImageSize.Width, pImageList.ImageSize.Height);
                    Gfx = Graphics.FromImage(MaskBmp);
                    IntPtr Hdc = Gfx.GetHdc();
                    ExtCursor.ImageList_Draw(pImageList.Handle, pImageIndex, Hdc, 0, 0, ILD_MASK);
                    Gfx.ReleaseHdc(Hdc);
                    CursorBmp = (Bitmap)pImageList.Images[pImageIndex];
                    // get the bitmap handles...
                    hMask = MaskBmp.GetHbitmap();
                    hImage = CursorBmp.GetHbitmap();
                    // create the actual cursor...
                    ICONINFO IconInfo = new ICONINFO();
                    IconInfo.fIcon = 0;
                    IconInfo.xHotspot = 5;
                    IconInfo.yHotspot = 5;
                    IconInfo.hbmMask = hMask;
                    IconInfo.hbmColor = hImage;
                    AssignHCursor(CreateIconIndirect(IconInfo), true);
                }
                finally
                {
                    if (Gfx != null)
                    {
                        Gfx.Dispose();
                    }
                    if (MaskBmp != null)
                    {
                        MaskBmp.Dispose();
                    }
                    if (CursorBmp != null)
                    {
                        CursorBmp.Dispose();
                    }
                    if (hMask != IntPtr.Zero)
                    {
                        DeleteObject(hMask);
                    }
                    if (hImage != IntPtr.Zero)
                    {
                        DeleteObject(hImage);
                    }
                }
            }
        }

        // ========================================================================
        private Bitmap[] CreateImageAndMask(Bitmap pCursorBitmap, Color pTransparentColor, bool pWithCrossHairs)
        {
            Bitmap[] Result = new Bitmap[2];
            Bitmap MaskBmp;
            Bitmap CursorBmp;
            Bitmap TempBmp = null;
            // use an imagelist to create a mask image...
            ImageList TempImgList = null;
            Graphics Gfx = null;
            Brush FillBrush = null;
            try
            {
                if (pWithCrossHairs)
                {
                    MaskBmp = new Bitmap(pCursorBitmap.Width * 2, pCursorBitmap.Height * 2);
                    TempBmp = new Bitmap(pCursorBitmap.Width * 2, pCursorBitmap.Height * 2);
                    Gfx = Graphics.FromImage(TempBmp);
                    FillBrush = new SolidBrush(pTransparentColor);
                    Gfx.FillRectangle(FillBrush, 0, 0, pCursorBitmap.Width * 2, pCursorBitmap.Height * 2);
                    Gfx.DrawLine(SystemPens.WindowText, 5, 0, 5, 10);
                    Gfx.DrawLine(SystemPens.WindowText, 0, 5, 10, 5);
                    Gfx.DrawImage(pCursorBitmap, new Rectangle(7, 7, pCursorBitmap.Width, pCursorBitmap.Height));
                    Gfx.Dispose();
                    Gfx = null;
                    TempImgList = new ImageList();
                    TempImgList.TransparentColor = pTransparentColor;
                    TempImgList.ImageSize = new Size(pCursorBitmap.Width * 2, pCursorBitmap.Height * 2);
                    TempImgList.Images.Add(TempBmp, pTransparentColor);
                    Gfx = Graphics.FromImage(MaskBmp);
                    IntPtr Hdc = Gfx.GetHdc();
                    ExtCursor.ImageList_Draw(TempImgList.Handle, 0, Hdc, 0, 0, ILD_MASK);
                    Gfx.ReleaseHdc(Hdc);
                    CursorBmp = (Bitmap)TempImgList.Images[0];
                }
                else
                {
                    MaskBmp = new Bitmap(pCursorBitmap.Width, pCursorBitmap.Height);
                    TempImgList = new ImageList();
                    TempImgList.TransparentColor = pTransparentColor;
                    TempImgList.ImageSize = new Size(pCursorBitmap.Width, pCursorBitmap.Height);
                    TempImgList.Images.Add(pCursorBitmap, pTransparentColor);
                    Gfx = Graphics.FromImage(MaskBmp);
                    IntPtr Hdc = Gfx.GetHdc();
                    ExtCursor.ImageList_Draw(TempImgList.Handle, 0, Hdc, 0, 0, ILD_MASK);
                    Gfx.ReleaseHdc(Hdc);
                    CursorBmp = (Bitmap)TempImgList.Images[0];
                }
                Result[0] = CursorBmp;
                Result[1] = MaskBmp;
            }
            finally
            {
                if (TempBmp != null)
                {
                    TempBmp.Dispose();
                }
                if (FillBrush != null)
                {
                    FillBrush.Dispose();
                }
                if (Gfx != null)
                {
                    Gfx.Dispose();
                }
                if (TempImgList != null)
                {
                    TempImgList.Dispose();
                }
            }
            return Result;
        }

        // ========================================================================
        private void ConstructFromImage(Bitmap pCursorImage, Bitmap pCursorMaskImage, Point pHotSpot)
        {
            IntPtr hMask = IntPtr.Zero;
            IntPtr hImage = IntPtr.Zero;
            try
            {
                hMask = pCursorMaskImage.GetHbitmap();
                hImage = pCursorImage.GetHbitmap();
                ICONINFO IconInfo = new ICONINFO();
                IconInfo.fIcon = 0;
                IconInfo.xHotspot = pHotSpot.X;
                IconInfo.yHotspot = pHotSpot.Y;
                IconInfo.hbmMask = hMask;
                IconInfo.hbmColor = hImage;
                AssignHCursor(CreateIconIndirect(IconInfo), true);
            }
            finally
            {
                if (hMask != IntPtr.Zero)
                {
                    DeleteObject(hMask);
                }
                if (hImage != IntPtr.Zero)
                {
                    DeleteObject(hImage);
                }
            }
        }
        #endregion //"Construct from image methods"

        #region "Loading methods"
        // ========================================================================
        private void LoadFromStreamEx(byte[] pCursorData, bool pDefaultSize, Size pPreferredSize)
        {
            MemoryStream LoadStream = new MemoryStream(pCursorData);
            try
            {
                LoadFromStreamEx(LoadStream, pDefaultSize, pPreferredSize);
            }
            finally
            {
                LoadStream.Dispose();
            }
        }

        // ========================================================================
        private bool LoadFromStreamEx(Stream pCursorStream, bool pDefaultSize, Size pPreferredSize)
        {
            bool Result = false;
            FileStream TempStream = null;
            string TempFileName = "";
            try
            {
                TempFileName = System.IO.Path.GetTempFileName();
                TempStream = new FileStream(TempFileName, FileMode.Open, FileAccess.Write, FileShare.None);
                StreamTransfer(pCursorStream, TempStream);
                // belt'n'braces...
                TempStream.Flush();
                TempStream.Close();
                TempStream.Dispose();
                TempStream = null;
                // load from temp file...
                Result = LoadFromFileEx(TempFileName, pDefaultSize, pPreferredSize);
            }
            finally
            {
                if (TempStream != null)
                {
                    TempStream.Close();
                    TempStream.Dispose();
                    TempStream = null;
                }
                if ((TempFileName != "") && File.Exists(TempFileName))
                {
                    try
                    {
                        File.Delete(TempFileName);
                    }
                    catch
                    {
                        // swallow exceptions
                        // worst case - temp file may not have been deleted?
                    }
                }
            }
            return Result;
        }

        // ========================================================================
        private bool LoadFromFileEx(string pFilename, bool pDefaultSize, Size pPreferredSize)
        {
            _DefaultSize = pDefaultSize;
            _PreferredSize = new Size(pPreferredSize.Width, pPreferredSize.Height);
            int Flags = LR_DEFAULTCOLOR | LR_LOADFROMFILE;
            if (_DefaultSize)
            {
                Flags = Flags | LR_DEFAULTSIZE;
            }
            return AssignHCursor(LoadImage(IntPtr.Zero, pFilename, IMAGE_CURSOR, _PreferredSize.Width, _PreferredSize.Height, Flags), true);
        }

        // ========================================================================
        private void LoadFromStream(byte[] pCursorData)
        {
            MemoryStream LoadStream = new MemoryStream(pCursorData);
            try
            {
                LoadFromStream(LoadStream);
            }
            finally
            {
                LoadStream.Dispose();
            }
        }

        // ========================================================================
        private void LoadFromStream(Stream pCursorStream)
        {
            FileStream TempStream = null;
            string TempFileName = "";
            try
            {
                TempFileName = System.IO.Path.GetTempFileName();
                TempStream = new FileStream(TempFileName, FileMode.Open, FileAccess.Write, FileShare.None);
                StreamTransfer(pCursorStream, TempStream);
                // belt'n'braces...
                TempStream.Flush();
                TempStream.Close();
                TempStream.Dispose();
                TempStream = null;
                int Flags = LR_DEFAULTCOLOR | LR_LOADFROMFILE;
                if (_DefaultSize)
                {
                    Flags = Flags | LR_DEFAULTSIZE;
                }
                if (!AssignHCursor(ExtCursor.LoadImage(IntPtr.Zero, TempFileName, IMAGE_CURSOR, _PreferredSize.Width, _PreferredSize.Height, Flags), true))
                {
                    throw new Exception("Unable to load cursor");
                }
            }
            finally
            {
                if (TempStream != null)
                {
                    TempStream.Close();
                    TempStream.Dispose();
                    TempStream = null;
                }
                if ((TempFileName != "") && File.Exists(TempFileName))
                {
                    try
                    {
                        File.Delete(TempFileName);
                    }
                    catch
                    {
                        // swallow exceptions
                        // worst case - temp file may not have been deleted?
                    }
                }
            }
        }
        #endregion //"Loading methods"

        #region "Cursor drop and build"
        // ========================================================================
		private void DropCursor(bool disposing)
		{
			if (_Cursor != null)
			{
				_Cursor.Dispose();
				_Cursor = null;
			}
            if (_OwnedHandle && (_HCursor != IntPtr.Zero))
            {
                // we own the handle to the cursor - so it's our responsibility to destroy it...
                try
                {
                    if (DestroyCursor(_HCursor))
                    {
                        _HCursor = IntPtr.Zero;
                        _OwnedHandle = false;
                        if (!disposing)
                        {
                            // invoke HandleDestroyed events (inadvisable to raise events during disposal though)...
                            DoHandleDestroyed();
                        }
                    }
                }
                catch 
#if DEBUG
                    (Exception ex)
#endif
                {
                    // swallow exceptions
                    // worst case - unknown scenario
#if DEBUG
                    throw ex;
#endif
                }
            }
		}

		// ========================================================================
		private void ReBuildCursor()
		{
            // drop the existing cursor (and handle, if neccessary)...
			DropCursor(false);
            if (!DesignMode && _SharedHandle && 
                ((_LoadFrom == _DesignLoadCursorFrom.File) || (_LoadFrom == _DesignLoadCursorFrom.ResxResource)))
            {
                // get the handle from shared handle repository...
                if (ExtCursorsSharedRepository.Instance.AssignSharedHandle(this, _DefaultSize, _PreferredSize, null))
                {
                    // shared handle used - no further action required...
                    return;
                }
            }
            if (!DesignMode)
            {
                // remove any previous handle sharing...
                ExtCursorsSharedRepository.Instance.RemovePreviousReferences(this, true);
            }
			bool Loaded = false;
            if (_CursorStream != null)
			{
                LoadFromStreamEx(_CursorStream, _DefaultSize, _PreferredSize);
			}
			else if (_LoadFrom == _DesignLoadCursorFrom.File)
			{
                LoadFromFileEx(LocalPath, _DefaultSize, _PreferredSize);
				if (DesignMode && (_Cursor != null))
				{
                    // get the stream so it matches the file specified...
                    LoadCursorStreamFromFile(_CursorLocation);
				}
			}
            else if (_LoadFrom == _DesignLoadCursorFrom.ResxResource)
            {
                if (DesignMode)
                {
                    // load it directly from the originating file in the resource...
                    Loaded = LoadFromFileEx(_Filename, _DefaultSize, _PreferredSize);
                    if (Loaded)
                    {
                        // get the stream so it matches the file specified...
                        LoadCursorStreamFromFile(_Filename);
                    }
                }
                else
                {
                    // load directly from resource at runtime...
                    try
                    {
                        Assembly ExecAssy = Assembly.GetEntryAssembly();
                        ResourceManager ResX = new ResourceManager(_ResXName, ExecAssy);
                        byte[] CurData;
                        object obj = ResX.GetObject(_ResourceName, null);
                        CurData = (byte[])obj;
                        _CursorStream = new MemoryStream(CurData);
                        // try to load it from stream...
                        LoadFromStreamEx(_CursorStream, _DefaultSize, _PreferredSize);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Error loading cursor resource: " + _ResXName + "." + _ResourceName + "\r" + ex.Message, "ExtCursor Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
		}

        // ========================================================================
        internal string LocalPath
        {
            get
            {
                if (!DesignMode && _CursorFileLocal)
                {
                    string CursorPath = _CursorLocation;
                    string LocalPath = Path.GetDirectoryName(Application.ExecutablePath);
                    string SubPath = Path.GetDirectoryName(_CursorLocation);
                    bool FileExists = false;
                    // the file maybe designated local - but the original path might have sub-directories...
                    do
                    {
                        CursorPath = LocalPath + @"\" + Path.GetFileName(CursorPath);
                        FileExists = File.Exists(CursorPath);
                        if (!FileExists)
                        {
                            if (SubPath == "")
                            {
                                break;
                            }
                            LocalPath = LocalPath + @"\" + Path.GetFileName(SubPath);
                            SubPath = Path.GetDirectoryName(SubPath);
                        }
                    } while (!FileExists);
                    return CursorPath;
                }
                else
                {
                    return _CursorLocation;
                }
            }
        }

        // ========================================================================
        internal bool AssignHCursor(IntPtr HCursor, bool Owned)
        {
            bool Result = false;
            if (HCursor != IntPtr.Zero)
            {
                Result = true;
                _OwnedHandle = Owned;
                _HCursor = HCursor;
                _Cursor = new Cursor(_HCursor);
                // do HandleCreated events...
                DoHandleCreated();
            }
            return Result;
        }

        // ========================================================================
        private static void StreamTransfer(Stream Source, Stream Destination)
        {
            int Len = System.Convert.ToInt32(Source.Length);
            Source.Seek(0, SeekOrigin.Begin);
            byte[] Buffer = new byte[Len];
            Source.Read(Buffer, 0, Len);
            Destination.Write(Buffer, 0, Len);
            Source.Seek(0, SeekOrigin.Begin);
        }

        // ========================================================================
        private void ClearAll()
        {
            ClearCursorStream();
            _LoadFrom = _DesignLoadCursorFrom.None;
            _Filename = "";
            _CursorLocation = "";
            _ResourceName = "";
            _ResXName = "";
        }

        // ========================================================================
        private void ClearCursorStream()
        {
            if (_CursorStream != null)
            {
                _CursorStream.Dispose();
                _CursorStream = null;
            }
        }

        // ========================================================================
        private bool LoadCursorStreamFromFile(string Filename)
        {
            bool Result = false;
            ClearCursorStream();
            FileStream Reader = null;
            try
            {
                Reader = new FileStream(Filename, FileMode.Open, FileAccess.Read);
                _CursorStream = new MemoryStream();
                StreamTransfer(Reader, _CursorStream);
                Result = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error loading cursor from filename: " + Filename + "\r" + ex.Message, "ExtCursor Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                ClearCursorStream();
            }
            finally
            {
                if (Reader != null)
                {
                    Reader.Close();
                    Reader.Dispose();
                }
            }
            return Result;
        }
        #endregion //"Cursor drop and build"

        #region "Do Events methods"
        //=====================================================================
        internal void DoHandleCreated()
        {
            if (!DesignMode && !_Initializing)
            {
                Delegate EventDelegate = Events[EventHandleCreated];
                if (EventDelegate != null)
                {
                    EventDelegate.DynamicInvoke(new object[] { new EventArgs() });
                }
            }
        }

        //=====================================================================
        private void DoHandleDestroyed()
        {
            if (!DesignMode && !_Initializing)
            {
                Delegate EventDelegate = Events[EventHandleDestroyed];
                if (EventDelegate != null)
                {
                    EventDelegate.DynamicInvoke(new object[] { new EventArgs() });
                }
            }
        }
        #endregion //"Do Events methods"

        #region "Public Properties"
        #region "Public Properties - Read-only, non-browsable"
        // ========================================================================
        /// <summary>
        /// Gets the System.Windows.Cursor contained in this ExtCursor.
        /// </summary>
        [Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [ReadOnly(true)]
		public Cursor Cursor
		{
			get
			{
				return _Cursor;
			}
		}

        // ========================================================================
        /// <summary>
        /// Gets handle of the cursor.
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [ReadOnly(true)]
        public IntPtr Handle
        {
            get
            {
                return _HCursor;
            }
        }

        // ========================================================================
        /// <summary>
        /// Gets a value indicating whether the cursor handle has been created.
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [ReadOnly(true)]
        public bool IsHandleCreated
        {
            get
            {
                return (_HCursor != IntPtr.Zero);
            }
        }
        #endregion //"Public Properties - Read-only, non-browsable"

        #region "Public Properties - non-browsable loading"
        // ========================================================================
        /// <summary>
        /// [Form Initialization only - DO NOT USE AT RUNTIME]
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [RefreshProperties(RefreshProperties.All)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public ExtCursorFileStreamer CursorStream
        {
            get
            {
                if ((_LoadFrom == _DesignLoadCursorFrom.LocalResource) && (_CursorStream != null))
                {
                    // from local resource and stream has been loaded...
                    return new ExtCursorFileStreamer(_CursorStream);
                }
                else
                {
                    // when the cursor is not loaded from local resource
                    // return null to prevent the cursor stream from being serialized into the forms resources...
                    return null;
                }
            }
            set
            {
                if (value.CursorData.Length == 0)
                {
                    _CursorStream = null;
                }
                else
                {
                    _CursorStream = new MemoryStream();
                    _CursorStream.Write(value.CursorData, 0, value.CursorData.Length);
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// [Form Initialization only - DO NOT USE AT RUNTIME]
        /// </summary>
        [Browsable(false)]
        [DefaultValue("")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public string Resource
        {
            get
            {
                if (_LoadFrom == _DesignLoadCursorFrom.ResxResource)
                {
                    return _Filename + ";" + _ResXName + ";" + _ResourceName;
                }
                else
                {
                    return "";
                }
            }
            set
            {
                if (value != "")
                {
                    _CursorLocation = "";
                    _Filename = "";
                    _ResourceName = "";
                    _ResXName = "";
                    string[] ResBits = value.Split(new char[] { ';' });
                    if (ResBits.Length == 3)
                    {
                        _LoadFrom = _DesignLoadCursorFrom.ResxResource;
                        _Filename = ResBits[0];
                        _ResXName = ResBits[1];
                        _ResourceName = ResBits[2];
                        if (!_Initializing)
                        {
                            if (!LoadCursorStreamFromFile(_Filename))
                            {
                                ClearAll();
                            }
                            ReBuildCursor();
                        }
                    }
                }
            }
        }
        #endregion //"Public Properties - non-browsable loading"

        #region "Public Properties - Design browsable"
        // ========================================================================
        /// <summary>
        /// [Form Initialization only - DO NOT USE AT RUNTIME]
        /// </summary>
        [Category("Cursor")]
		[Description("The cursor stored in this component.")]
		[DefaultValue("")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		[RefreshProperties(RefreshProperties.All)]
		[Editor("ExtCursors.Design.ExtCursorEditor", typeof(UITypeEditor))]
		[TypeConverter("ExtCursors.Design.ExtCursorFileConverter")]
		[DisplayName("Cursor")]
        [DesignOnly(true)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public string CursorFile
		{
			get
			{
                if (_LoadFrom == _DesignLoadCursorFrom.ResxResource)
                {
                    return _Filename + ";" + _ResXName + ";" + _ResourceName;
                }
                else
                {
                    return _Filename;
                }
			}
			set
			{
                if (DesignMode)
                {
                    if (value != _Filename)
                    {
                        if (value == "")
                        {
                            // none...
                            ClearAll();
                            ReBuildCursor();
                        }
                        else if (value.IndexOf(';') > -1)
                        {
                            // from resource...
                            string[] ResBits = value.Split(new char[] { ';' });
                            if (ResBits.Length == 3)
                            {
                                _LoadFrom = _DesignLoadCursorFrom.ResxResource;
                                _CursorLocation = "";
                                _Filename = ResBits[0];
                                _ResXName = ResBits[1];
                                _ResourceName = ResBits[2];
                                if (!_Initializing)
                                {
                                    if (!LoadCursorStreamFromFile(_Filename))
                                    {
                                        ClearAll();
                                    }
                                }
                            }
                            else
                            {
                                ClearAll();
                            }
                            ReBuildCursor();
                        }
                        else if (File.Exists(value))
                        {
                            // from local (form) resource...
                            _LoadFrom = _DesignLoadCursorFrom.LocalResource;
                            _Filename = value;
                            _SharedHandle = false;
                            _CursorLocation = "";
                            _ResourceName = "";
                            _ResXName = "";
                            if (!_Initializing)
                            {
                                if (!LoadCursorStreamFromFile(_Filename))
                                {
                                    ClearAll();
                                }
                                ReBuildCursor();
                            }
                        }
                        else
                        {
                            // invalid...
                            ClearAll();
                            ReBuildCursor();
                        }
                    }
                }
			}
		}

		// ========================================================================
        /// <summary>
        /// [Form Initialization only - DO NOT USE AT RUNTIME]
        /// </summary>
        [Category("Cursor")]
		[Description("Specifies the file location from which the cursor is loaded at runtime.")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[RefreshProperties(RefreshProperties.All)]
		[DefaultValue("")]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public string CursorLocation
		{
			get
			{
				return _CursorLocation;
			}
			set
			{
				if (value != _CursorLocation)
				{
                    if (DesignMode && !File.Exists(value))
                    {
                        throw new Exception("The cursor file '" + value + "' does not exist");
                    }
                    _LoadFrom = _DesignLoadCursorFrom.File;
					_CursorLocation = value;
                    _Filename = "";
                    _ResourceName = "";
                    _ResXName = "";
					if (!_Initializing)
					{
                        if (!LoadCursorStreamFromFile(_CursorLocation))
                        {
                            ClearAll();
                        }
                        ReBuildCursor();
                    }
				}
			}
		}

		// ========================================================================
        /// <summary>
        /// Gets or sets whether cursor file location is local to the application at runtime [DESIGN ONLY]
        /// </summary>
        [Category("Cursor")]
		[Description("Determines whether the cursor file, specified by CursorLocation, will be in the application directory at runtime.")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[RefreshProperties(RefreshProperties.All)]
		[DefaultValue(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool CursorLocationLocal
		{
			get
			{
				return _CursorFileLocal;
			}
			set
			{
				_CursorFileLocal = value;
			}
        }

        // ========================================================================
        /// <summary>
        /// Gets or sets whether cursor handle is to be shared.
        /// </summary>
        [Category("Cursor")]
        [Description("Determines whether the cursor handle is shared at runtime - the handle is re-used by all ExtCursor components using the same cursor source.\r\rShared handles can only be used where the cursor is loaded from a file or project resource - not when the cursor is loaded from a local (form) resource.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [RefreshProperties(RefreshProperties.All)]
        [DefaultValue(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool SharedHandle
        {
            get
            {
                return _SharedHandle;
            }
            set
            {
                if (_Initializing || (_LoadFrom == _DesignLoadCursorFrom.ResxResource) || (_LoadFrom == _DesignLoadCursorFrom.File))
                {
                    _SharedHandle = value;
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Gets or sets the preferred size of the cursor to be loaded.
        /// </summary>
        [Category("Cursor Sizing")]
        [Description("The preferred size of the cursor.\r\rIf this property is set to (0,0) and the SizeDefault property is set to 'true' then default system metric size for cursors is used.  If this property is set to (0,0) and the SizeDefault property is set to 'false' then the actual size of the cursor is used (if the cursor contains multiple sizes then the first is used).")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [RefreshProperties(RefreshProperties.All)]
        [DefaultValue(typeof(Size), "0,0")]
        public Size SizePreferred
        {
            get
            {
                return _PreferredSize;
            }
            set
            {
                if (_LoadFrom == _DesignLoadCursorFrom.FromImage)
                {
                    throw new Exception("SizePreferred property cannot be set on cursors created from an image.");
                }
                if ((value.Width != _PreferredSize.Width) || (value.Height != _PreferredSize.Height))
                {
                    _PreferredSize = new Size(value.Width, value.Height);
                    if (!_Initializing)
                    {
                        ReBuildCursor();
                    }
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Gets or sets a value indicating whether the default system metric cursor size should be used when loading.
        /// </summary>
        [Category("Cursor Sizing")]
        [Description("Determines whether to use default system metric size for the cursor.\r\rIf this property is 'true' and the SizePreferred is (0,0) the default system metric size for cursors is used.  If this property is 'false' and the SizePreferred is (0,0) then the actual size of the cursor is used (if the cursor contains multiple sizes then the first is used).")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [RefreshProperties(RefreshProperties.All)]
        [DefaultValue(true)]
        public bool SizeDefault
        {
            get
            {
                return _DefaultSize;
            }
            set
            {
                if (_LoadFrom == _DesignLoadCursorFrom.FromImage)
                {
                    throw new Exception("SizeDefault property cannot be set on cursors created from an image.");
                }
                if (value != _DefaultSize)
                {
                    _DefaultSize = value;
                    if (!_Initializing)
                    {
                        ReBuildCursor();
                    }
                }
            }
        }
        #endregion //"Public Properties - Design browsable"

        #region "Public Properties - Design browsable (informational, read-only)"
        // ========================================================================
        /// <summary>
        /// Gets the cursor hotspot.
        /// </summary>
        [Category("Information")]
        [Description("The HotSpot point within the cursor.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [RefreshProperties(RefreshProperties.All)]
        [DefaultValue(typeof(Point), "0,0")]
        [ParenthesizePropertyName(true)]
        [ReadOnly(true)]
        public Point HotSpot
        {
            get
            {
                if (_Cursor != null)
                {
                    return _Cursor.HotSpot;
                }
                else
                {
                    return new Point(0, 0);
                }
            }
        }

        // ========================================================================
        /// <summary>
        /// Gets the cursor size.
        /// </summary>
        [Category("Information")]
        [Description("The size of the cursor.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [RefreshProperties(RefreshProperties.All)]
        [DefaultValue(typeof(Size), "0,0")]
        [ParenthesizePropertyName(true)]
        [ReadOnly(true)]
        public Size Size
        {
            get
            {
                if (_Cursor != null)
                {
                    return _Cursor.Size;
                }
                else
                {
                    return new Size(0, 0);
                }
            }
        }
        #endregion //"Public Properties - Design browsable (informational, read-only)"
        #endregion //"Public Properties"

        #region "Events"
        // ========================================================================
        /// <summary>
        /// Occurs when a handle is created for the cursor.
        /// </summary>
        [Category("Events")]
        [Description("Occurs when the cursor handle is created.")]
        public event EventHandler HandleCreated
        {
            add
            {
                Events.AddHandler(EventHandleCreated, value);
            }
            remove
            {
                Events.RemoveHandler(EventHandleCreated, value);
            }
        }

        // ========================================================================
        /// <summary>
        /// Occurs when the cursor handle is destroyed.
        /// </summary>
        [Category("Events")]
        [Description("Occurs when the cursor handle is destroyed.")]
        public event EventHandler HandleDestroyed
        {
            add
            {
                Events.AddHandler(EventHandleCreated, value);
            }
            remove
            {
                Events.RemoveHandler(EventHandleCreated, value);
            }
        }
        #endregion //"Events"

        #region "Disposal methods"
        // ========================================================================
		protected override void Dispose(bool disposing)
		{
#if DEBUG
            System.Diagnostics.Debug.WriteLine("ExtCursor.Dispose(" + disposing.ToString() + ")  [_Disposed = " + _Disposed.ToString() + "]");
#endif
            if (!_Disposed)
            {
                if (_SharedHandle)
                {
                    if (ExtCursorsSharedRepository.Exists)
                    {
                        ExtCursorsSharedRepository.Instance.ExtCursor_Disposed(this);
                    }
                }
                DropCursor(true);
                if (_CursorStream != null)
                {
                    _CursorStream.Dispose();
                }
                _Disposed = true;
            }
            base.Dispose(disposing);
        }
        #endregion //"Disposal methods"

        #region "ISupportInitialize Members"
        // ========================================================================
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void BeginInit()
		{
			_Initializing = true;
		}

		// ========================================================================
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void EndInit()
		{
            if (_Initializing)
            {
                _Initializing = false;
                ReBuildCursor();
            }
        }
        #endregion //"ISupportInitialize Members"
    }
    #endregion //"Class : ExtCursor"

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
I've been involved in software design and development for more years than I care to remember. Started out in Engineering and drifted into computing as a real-time software engineer (assembler) working on industrial robotic systems.
Moved into application development (in Clipper, Delphi and, more recently, .Net) in a wide variety of industries including banking, manufacturing, betting & gaming, travel industry, sport (Formula 1), public sector and a few others.
Spent many years involved in designing and developing commercial websites, becoming a specialist in XML and XSLT. Designed and developed an XSLT IDE (Xselerator), which is now available free on SourceForge.

Comments and Discussions