Click here to Skip to main content
15,891,316 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.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace ExtCursors.Design
{
    #region "Class : ExtCursorSelectDropDown"
    //=========================================================================
    //=========================================================================
    [ToolboxItem(false)]
    public partial class ExtCursorSelectDropDown : UserControl
    {
        private ITypeDescriptorContext _Context = null;
        private IWindowsFormsEditorService _EditorService;
        private bool _InternalResizing = false;
        private static int _PreferredHeight = -1;
        private Size _CursorSize;
        private int _TextHeight = -1;
        private bool _MouseDown = false;
        private object _CurrentValue = null;
        internal ExtCursor _SelectedValue = null;
        internal bool _Cancelled = true;
        private StringFormat _StringFormat;

        //=========================================================================
        public ExtCursorSelectDropDown(ITypeDescriptorContext pContext, IWindowsFormsEditorService pEditorService, object pCurrentValue)
        {
            _Context = pContext;
            _EditorService = pEditorService;
            _CurrentValue = pCurrentValue;
            _Cancelled = true;
            _MouseDown = false;
            _StringFormat = new StringFormat(StringFormatFlags.NoWrap);
            _StringFormat.Trimming = StringTrimming.EllipsisCharacter;
            _StringFormat.Alignment = StringAlignment.Near;
            _StringFormat.LineAlignment = StringAlignment.Center;
            _TextHeight = -1;

            InitializeComponent();

            // get the size of a cursor...
            Cursor TestCursor = System.Windows.Forms.Cursors.Arrow;
            _CursorSize = TestCursor.Size;
            this.listBox_ExtCursors.ItemHeight = _CursorSize.Height + 5;
            this.listBox_ExtCursors.BeginUpdate();
            // add the (none) option...
            this.listBox_ExtCursors.Items.Add(new object());
            int SelIndex = 0;
            // add the ExtCursors...
            int Idx;
            if (_Context != null)
            {
                if (_Context.Container != null)
                {
                    try
                    {
                        // get the top container (the form) - because that's where the ExtCursor components live...
                        IDesignerHost DesignerHost = (IDesignerHost)_Context.GetService(typeof(IDesignerHost));
                        IContainer TopContainer = DesignerHost.RootComponent.Site.Container;
                        foreach (object Ctrl in TopContainer.Components)
                        {
                            if (Ctrl is ExtCursor)
                            {
                                Idx = this.listBox_ExtCursors.Items.Add(Ctrl);
                                if (Ctrl == _CurrentValue)
                                {
                                    SelIndex = Idx;
                                }
                            }
                        }
                    }
                    catch
                    {
                        // swallow exceptions
                        // feedback (i.e. MessageBox) could cause more problems
                        // worst case - dropdown list empty or partially filled
                    }
                }
            }
            Graphics gfx = null;
            try
            {
                gfx = Graphics.FromHwnd(this.Handle);
                SizeF TxtSize = gfx.MeasureString("([Hg", this.listBox_ExtCursors.Font);
                _TextHeight = System.Convert.ToInt32(TxtSize.Height);
                gfx.Dispose();
            }
            catch
            {
                _TextHeight = 16;
            }
            finally
            {
                if (gfx != null)
                {
                    gfx.Dispose();
                }
            }
            this.listBox_ExtCursors.SelectedIndex = SelIndex;
            this.listBox_ExtCursors.EndUpdate();
            _InternalResizing = true;
            int ItemsCount = Math.Min(this.listBox_ExtCursors.Items.Count, 9);
            if ((ExtCursorSelectDropDown._PreferredHeight == -1) || (ItemsCount == 1))
            {
                // resize according to the number of items...
                int ItemHeight = Math.Max(_CursorSize.Height + 5, _TextHeight + 2);
                this.ClientSize = new Size(this.ClientSize.Width, (_TextHeight + 2) + ((ItemsCount - 1) * ItemHeight));
            }
            else
            {
                this.ClientSize = new Size(this.ClientSize.Width, ExtCursorSelectDropDown._PreferredHeight);
            }
            _InternalResizing = false;
        }

        //=========================================================================
        private void ExtCursorSelectDropDown_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
            {
                _Cancelled = false;
            }
        }

        //=========================================================================
        private void listBox_ExtCursors_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            if (_TextHeight == -1)
            {
                SizeF TxtSize = e.Graphics.MeasureString("([Hg", this.listBox_ExtCursors.Font);
                _TextHeight = System.Convert.ToInt32(TxtSize.Height);
            }
            if (e.Index == 0)
            {
                e.ItemHeight = _TextHeight + 2;
            }
            else
            {
                e.ItemHeight = Math.Max(_CursorSize.Height + 5, _TextHeight + 2);
            }
        }

        //=========================================================================
        private void listBox_ExtCursors_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index > -1)
            {
                Brush TextBrush = SystemBrushes.WindowText;
                Rectangle TextRect;
                if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
                {
                    e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
                    TextBrush = SystemBrushes.HighlightText;
                }
                else
                {
                    e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
                }
                if (e.Index == 0)
                {
                    // draw none...
                    TextRect = new Rectangle(new Point(e.Bounds.X + 2, e.Bounds.Y), new Size(e.Bounds.Width - 2, e.Bounds.Height));
                    e.Graphics.DrawString("(none)", this.listBox_ExtCursors.Font, TextBrush, TextRect, _StringFormat);
                }
                else
                {
                    ExtCursor ThisCursor = (ExtCursor)this.listBox_ExtCursors.Items[e.Index];
                    Rectangle CursorRect = new Rectangle(new Point(e.Bounds.X + 2, e.Bounds.Y + 2), _CursorSize);
                    e.Graphics.FillRectangle(SystemBrushes.ControlLight, CursorRect);
                    e.Graphics.DrawRectangle(SystemPens.WindowText, CursorRect);
                    if (ThisCursor._Cursor != null)
                    {
                        ThisCursor._Cursor.DrawStretched(e.Graphics, CursorRect);
                    }
                    TextRect = new Rectangle(new Point(e.Bounds.X + _CursorSize.Width + 5, e.Bounds.Y), new Size(e.Bounds.Width - (_CursorSize.Width + 5), e.Bounds.Height));
                    e.Graphics.DrawString(ThisCursor.Site.Name, this.listBox_ExtCursors.Font, TextBrush, TextRect, _StringFormat);
                }
            }
        }

        //=========================================================================
        private void listBox_ExtCursors_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            _MouseDown = true;
        }

        //=========================================================================
        private void listBox_ExtCursors_MouseDown(object sender, MouseEventArgs e)
        {
            _MouseDown = true;
        }

        //=========================================================================
        private void listBox_ExtCursors_MouseUp(object sender, MouseEventArgs e)
        {
            _MouseDown = false;
        }

        //=========================================================================
        private void listBox_ExtCursors_SelectedValueChanged(object sender, EventArgs e)
        {
            if (this.listBox_ExtCursors.SelectedIndex != -1)
            {
                if (this.listBox_ExtCursors.SelectedIndex == 0)
                {
                    _SelectedValue = null;
                }
                else
                {
                    _SelectedValue = (ExtCursor)this.listBox_ExtCursors.Items[this.listBox_ExtCursors.SelectedIndex];
                }
                if (_MouseDown)
                {
                    _Cancelled = false;
                    _EditorService.CloseDropDown();
                }
            }
        }

        //=========================================================================
        private void ExtCursorSelectDropDown_Resize(object sender, EventArgs e)
        {
            if (!_InternalResizing && (this.listBox_ExtCursors.Items.Count > 1))
            {
                ExtCursorSelectDropDown._PreferredHeight = this.ClientSize.Height;
            }
        }


    }
    #endregion
}

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