vbAccelerator - Contents of code file: CheckedIconListBoxLib.cs

using System;
using System.Windows.Forms;
using System.Drawing;
using vbAccelerator.Components.ImageList;

namespace vbAccelerator.Controls.ListBox
{


   #region CheckedIconListBox
   /// <summary>
   /// A simple owner-draw ListBox implementation which
   /// displays Images from a ComCtl32.DLL ImageList.
   /// Easy to modify to use a standard Forms ImageList
   /// if you wanted, but unfortunately this class is 
   /// sealed and it is not possible to use it with
   /// the shell's System Image List, which is what
   /// is needed for this sample.
   /// 
   /// Currently, there is no override for the Add method
   /// etc.  This means you can add any sort of object to
   /// the box, but the actual box itself requires that
   /// you add a CheckedIconItem object, otherwise you
   /// will get an exception.  Not ideal but on deadline.
   /// </summary>
   public class CheckedIconListBox : CheckedListBox
   {
      #region Enumerations
      public enum ItemHighlightStyle
      {
         system,
         xp
      }
      #endregion

      #region Member Variables
      private int iconWidth = 16;
      private int iconHeight = 16;
      private SysImageList sysIls;
      private ItemHighlightStyle highlightStyle = ItemHighlightStyle.system;
      #endregion

      #region Implementation
      /// <summary>
      /// Gets/sets whether highlighting is drawn using alpha 
      /// </summary>
      public ItemHighlightStyle HighlightStyle
      {
         get
         {
            return highlightStyle;
         }
         set
         {
            highlightStyle = value;
         }
      }

      /// <summary>
      /// Gets/sets a System Image List for icons in the control
      /// </summary>
      public SysImageList SystemImageList
      {
         get 
         {
            return sysIls;
         }
         set
         {
            sysIls = value;
         }
      }

      protected override void OnDrawItem (
       System.Windows.Forms.DrawItemEventArgs e )
      {
         if (base.DesignMode)
         {
            base.OnDrawItem(e);
         }
         else
         {
            if (e.Index>-1)
            {
               bool rightToLeft = (this.RightToLeft == RightToLeft.Yes);

               CheckedIconItem item = (CheckedIconItem)base.Items[e.Index];

               // no flickering: we create a shadow bitmap to draw 
               // into and only transfer once we've completed:
               Bitmap bmp = new Bitmap(e.Bounds.Width, e.Bounds.Height);
               Graphics gr = Graphics.FromImage(bmp);
               
               // fill the background:
               SolidBrush brBack;
               brBack = new SolidBrush(this.BackColor);
               gr.FillRectangle(brBack, 
                  0, 0, 
                  e.Bounds.Width, e.Bounds.Height);
               brBack.Dispose();

               // evaluate the indent:
               int indent = item.Indent *  iconWidth;
               Rectangle rcItem;
               if (rightToLeft)
               {
                  rcItem = new Rectangle(
                     0, 0, 
                     e.Bounds.Width - indent, e.Bounds.Height);
               }
               else
               {
                  rcItem = new Rectangle(
                     indent, 0, 
                     e.Bounds.Width - indent, e.Bounds.Height);
               }

               // Draw selection rectangle if necessary:
               bool noDispose = false;
               if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
               {
                  Brush brSelected = null;
                  if (highlightStyle == ItemHighlightStyle.xp)
                  {
                     brSelected = new SolidBrush(
                        Color.FromArgb(96, 
                        Color.FromKnownColor(KnownColor.Highlight)));
                     noDispose = false;
                  }
                  else
                  {
                     brSelected = SystemBrushes.Highlight;
                     noDispose = true;
                  }
                  gr.FillRectangle(brSelected, 
                     rcItem.Left, rcItem.Top,
                     rcItem.Width, rcItem.Height);
                  if (!noDispose)
                  {
                     brSelected.Dispose();
                  }
               }            

               // Draw the Check box:
               int pos = 0;
               if (rightToLeft)
               {
                  pos = rcItem.Right - iconWidth - 2;
               }
               else
               {
                  pos = rcItem.Left;
               }
               if (!item.NoCheckBox)
               {
                  ButtonState state = ButtonState.Normal;
                  if (!item.Enabled)
                  {
                     state = ButtonState.Inactive;
                  }
                  else
                  {
                     switch (GetItemCheckState(e.Index))
                     {
                        case CheckState.Checked:
                           state = ButtonState.Checked;
                           break;
                        case CheckState.Indeterminate:
                           state = ButtonState.Inactive;
                           break;
                     }
                  }
                  state |= ButtonState.Flat;
                  ControlPaint.DrawCheckBox(gr, pos, rcItem.Top, iconWidth,
                   iconHeight, state);
                  pos += (rightToLeft ? -(iconWidth+2) : iconWidth + 2);
               }

               // Draw the image onto the control, not the
               // offscreen bitmap:
               int iconLeft = pos;
               pos += (rightToLeft ? 0 : iconWidth + 2 );

               // Draw the Text:
               Brush brText = null;
               if ((highlightStyle == ItemHighlightStyle.xp) || ((e.State &
                DrawItemState.Selected) != DrawItemState.Selected))
               {
                  brText = new SolidBrush(base.ForeColor);
                  noDispose = false;
               }
               else
               {
                  brText = SystemBrushes.HighlightText;
                  noDispose = true;
               }
               RectangleF textRect;
               if (rightToLeft)
               {
                  textRect = new RectangleF(
                     0, 
                     rcItem.Top, 
                     pos,
                     rcItem.Height);
               }
               else
               {
                  textRect = new RectangleF(
                     pos, 
                     rcItem.Top,
                     rcItem.Right - pos,
                     rcItem.Height);
               }
               StringFormat textFormat = new StringFormat();
               textFormat.Trimming = StringTrimming.EllipsisCharacter;
               textFormat.Alignment = (rightToLeft ? StringAlignment.Far :
                StringAlignment.Near);
               Font itemFont = null;
               bool noFontDispose = true;
               if (item.Bold)
               {
                  itemFont = new Font(base.Font.FontFamily, base.Font.Size,
                   (base.Font.Style | FontStyle.Bold));
                  noFontDispose = false;
               }
               else
               {
                  itemFont = base.Font;
               }
               if (item.Enabled)
               {
                  gr.DrawString(item.Text, itemFont, brText, textRect,
                   textFormat);
               }
               else
               {
                  ControlPaint.DrawStringDisabled(
                     gr, item.Text, itemFont,
                      Color.FromKnownColor(KnownColor.ControlDark), 
                     textRect, textFormat);
               }
               textFormat.Dispose();
               if (!noFontDispose)
               {
                  itemFont.Dispose();
               }
               if (!noDispose)
               {
                  brText.Dispose();
               }

               // focus rectangle?
               if (
                  ((e.State & DrawItemState.Selected) ==
                   DrawItemState.Selected) &
                  ((e.State & DrawItemState.Focus ) == DrawItemState.Focus)
                  )
               {
                  ControlPaint.DrawFocusRectangle(gr, rcItem);
               }

               // Swap shadow bitmap to display:
               e.Graphics.DrawImage(bmp, e.Bounds, 0, 0, e.Bounds.Width,
                e.Bounds.Height, GraphicsUnit.Pixel);
               // Draw icon directly onto the control (otherwise the alpha
               // channel gets lost since DrawImage doesn't include alpha):
               if (item.IconIndex != -1)
               {
                  IntPtr hdc = e.Graphics.GetHdc();
                  sysIls.DrawImage(
                     hdc, 
                     item.IconIndex, 
                     iconLeft, 
                     e.Bounds.Top);
                  e.Graphics.ReleaseHdc(hdc);                  
               }

               // clear up:
               bmp.Dispose();
               gr.Dispose();
            }
            else
            {
               base.OnDrawItem(e);
            }
         }
      }

      public CheckedIconListBox()
      {
         this.DrawMode = DrawMode.OwnerDrawFixed;
      }

      #region CheckedIconItem
      /// <summary>
      /// Provides extended properties for an Item within the
      /// CheckedIconListBox.  All items added to the CheckedIconListBox
      /// must be of this type.
      /// </summary>
      public class CheckedIconItem : Object
      {
         #region Member Variables
         private int iconIndex = -1;
         private int indent = 0;
         private bool bold = false;
         private bool enabled = true;
         private bool noCheckBox = false;
         private string text = "";
         private Object data = null;
         #endregion

         #region Implementation
         /// <summary>
         /// Gets/sets the indentation of the item
         /// </summary>
         public int Indent
         {
            get
            {
               return this.indent;
            }
            set
            {
               this.indent = value;
            }
         }

         /// <summary>
         /// Gets/sets the zero-based icon index of the item
         /// </summary>
         public int IconIndex
         {
            get
            {
               return this.iconIndex;
            }
            set
            {
               this.iconIndex = value;
            }
         }

         /// <summary>
         /// Gets/sets whether the item is rendered with a Bold
         /// font.
         /// </summary>
         public bool Bold
         {
            get
            {
               return this.bold;
            }
            set
            {
               this.bold = value;
            }
         }

         /// <summary>
         /// Gets/sets whether the item is enabled or not
         /// </summary>
         public bool Enabled
         {
            get
            {
               return this.enabled;
            }
            set
            {
               this.enabled = value;
            }
         }

         /// <summary>
         /// Gets/sets whether the item should not have a check box.
         /// </summary>
         public bool NoCheckBox
         {
            get
            {
               return this.noCheckBox;
            }
            set
            {
               this.noCheckBox = value;
            }
         }

         /// <summary>
         /// Gets/sets the display text of the item
         /// </summary>
         public string Text
         {
            get
            {
               return this.text;
            }
            set
            {
               this.text = value;
            }
         }

         /// <summary>
         /// Gets/sets data associated with the item         
         /// </summary>
         public Object Data
         {
            get
            {
               return this.data;
            }
            set
            {
               this.data = value;
            }
         }

         public CheckedIconItem() : base()
         {
         }
         #endregion
      }
      #endregion

      #endregion

   }
   #endregion


}