vbAccelerator - Contents of code file: ListBarListView.cs

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;

namespace vbAccelerator.Components.ListBarControl
{
   /// <summary>
   /// An internal extension of the ListView control to add the
   /// specific functionality required to make the ListView 
   /// behave like the one in the Office Shortcut Bar control;
   /// specifically allowing the position of items to be 
   /// customised and providing access to the CustomDraw facility 
   /// of the ListView.
   /// </summary>
   internal class ListBarListView : System.Windows.Forms.ListView 
   {
      #region Unmanaged Code
      private const int WM_NOTIFY = 0x4E;

      private const int LVN_FIRST = -100;
      private const int LVN_LAST = -199;
      private const int LVN_GETINFOTIPA = (LVN_FIRST - 57);
      private const int LVN_GETINFOTIPW = (LVN_FIRST - 58);

      private const int LVM_FIRST = 0x1000;
      private const int LVM_GETITEMRECT = (LVM_FIRST + 14);
      private const int LVM_SETITEMPOSITION32 = (LVM_FIRST + 49);
      private const int LVM_SETICONSPACING = (LVM_FIRST + 53);

      private const int NM_FIRST = 0;
      private const int NM_CUSTOMDRAW = (NM_FIRST - 12);

      [DllImport("user32", CharSet=CharSet.Auto)]
      private extern static int SendMessage (
         IntPtr hWnd, 
         int wMsg , 
         int wParam , 
         IntPtr lParam);

      [StructLayout(LayoutKind.Sequential)]
         private struct POINTAPI
      {
         public int x;
         public int y;
      }

      [StructLayout(LayoutKind.Sequential)]
         private struct NMHDR
      {
         public IntPtr hwndFrom;
         public int idfrom;
         public int code;
      }

      [StructLayout(LayoutKind.Sequential)]
         private struct NMCUSTOMDRAW
      {
         public NMHDR hdr;
         public int dwDrawStage;
         public IntPtr hdc;
         public Rectangle rc;
         public int dwItemSpec;
         public int uItemState;
         public IntPtr lItemlParam;
      }
      #endregion

      public event System.EventHandler HandleChanged;

      private int iconSpaceX = 0;
      private int iconSpaceY = 0;

      public int IconSpaceX
      {
         get
         {
            return iconSpaceX;
         }
         set
         {
            iconSpaceX = value;
            if (this.Handle != IntPtr.Zero)
            {
               SetIconSpacing();
            }
         }
      }
      
      public int IconSpaceY
      {
         get
         {
            return iconSpaceY;
         }
         set
         {
            iconSpaceY = value;
            if (this.Handle != IntPtr.Zero)
            {
               SetIconSpacing();
            }
         }
      }

      private void SetIconSpacing()
      {
         unchecked
         {
            int lXY = 0;
            int lXYD = -1; //0xFFFFFFFF;;
            int lXYC = 0;
            int cX = 0, cY = 0;
      
            lXYC = SendMessage(this.Handle, LVM_SETICONSPACING, 0,
             (IntPtr)lXYD);
            // cX is loword:
            cX = (lXYC & 0xFFFF);
            // cY is hiword:
            cY = (lXYC / 0x10000);
            if (iconSpaceX > 0) 
            {
               cX = iconSpaceX;
            }
            if (iconSpaceY > 0)
            {
               cY = iconSpaceY;
            }   
            lXY = (cX & 0x7FFF);
            lXY |= ((cY & 0x7FFF) * 0x10000);

            SendMessage(this.Handle, LVM_SETICONSPACING, 0, (IntPtr)lXY);
         }
      }   
                                             
      public void SetItemPosition(int index, Point point)
      {
         POINTAPI pt = new POINTAPI();
         pt.x = point.X;
         pt.y = point.Y;
         IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(pt));
         Marshal.StructureToPtr(pt, lParam, false);
         int ret = SendMessage(this.Handle, 
            LVM_SETITEMPOSITION32,
            index,
            lParam);
         Marshal.FreeCoTaskMem(lParam);
      }

      protected override void OnHandleCreated ( System.EventArgs e )
      {
         base.OnHandleCreated(e);
         if (HandleChanged != null)
         {
            HandleChanged(this, e);
         }
      }

      protected override void WndProc ( ref System.Windows.Forms.Message m )
      {
         bool handled = false;
         switch (m.Msg)
         {
            case WM_NOTIFY:
               handled = OnWMNotify(ref m);
               break;
         }         
         
         if (!handled)
         {
            base.WndProc(ref m);
         }

      }

      private bool OnWMNotify(ref System.Windows.Forms.Message m)
      {
         bool handled = false;

         // Marshal lParam into NMHDR:
         NMHDR hdr = new NMHDR();
         hdr = (NMHDR)Marshal.PtrToStructure( m.LParam, hdr.GetType() );

         switch (hdr.code)
         {
            case NM_CUSTOMDRAW:
               NMCUSTOMDRAW customDraw = new NMCUSTOMDRAW();
               customDraw = (NMCUSTOMDRAW)Marshal.PtrToStructure( m.LParam,
                customDraw.GetType() );
               handled = OnCustomDraw(ref customDraw, ref m);

               break;

            case LVN_GETINFOTIPA:
               break;
            case LVN_GETINFOTIPW:
               break;
         }

         return handled;

      }

      private bool OnCustomDraw(ref NMCUSTOMDRAW customDraw, ref Message m) 
      {
         return false;
      }


      public ListBarListView() : base()
      {
      }
   }

}