#if FRAMEWORK20
using System;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using DevComponents.DotNetBar.Rendering;
using System.Globalization;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
namespace DevComponents.DotNetBar.Controls
{
    /// 
    /// Represents the extended ListView control with the Office 2007 Style.
    /// 
    [ToolboxBitmap(typeof(ListViewEx), "Controls.ListViewEx.ico"), ToolboxItem(true)]
    public class ListViewEx : ListView, INonClientControl
    {
        #region Private Variables
        private NonClientPaintHandler m_NCPainter = null;
        private ElementStyle m_BorderStyle = null;
        #endregion
        #region Constructor, Dispose
        public ListViewEx()
            : base()
        {
            m_BorderStyle = new ElementStyle();
            m_BorderStyle.Class = ElementStyleClassKeys.ListViewBorderKey;
            m_BorderStyle.StyleChanged += new EventHandler(BorderStyle_StyleChanged);
            m_NCPainter = new NonClientPaintHandler(this, eScrollBarSkin.Optimized);
            this.OwnerDraw = true;
            this.DoubleBuffered = true;
            this.BorderStyle = BorderStyle.None;
            StyleManager.Register(this);
        }
        protected override void Dispose(bool disposing)
        {
            StyleManager.Unregister(this);
            if (m_NCPainter != null)
            {
                m_NCPainter.Dispose();
                //m_NCPainter = null;
            }
            if (m_BorderStyle != null) m_BorderStyle.StyleChanged -= new EventHandler(BorderStyle_StyleChanged);
            base.Dispose(disposing);
        }
        #endregion
        #region Inernal Implementation
        private Font _ColumnHeaderFont = null;
        /// 
        /// Gets or sets the column header font. Default value is null which means controls Font property is used.
        /// 
        [DefaultValue(null), Category("Appearance"), Description("Indicates column header font.")]
        public Font ColumnHeaderFont
        {
            get { return _ColumnHeaderFont; }
            set
            {
                if (value != _ColumnHeaderFont)
                {
                    Font oldValue = _ColumnHeaderFont;
                    _ColumnHeaderFont = value;
                    OnColumnHeaderFontChanged(oldValue, value);
                }
            }
        }
        /// 
        /// Called when ColumnHeaderFont property has changed.
        /// 
        /// Old property value
        /// New property value
        protected virtual void OnColumnHeaderFontChanged(Font oldValue, Font newValue)
        {
            if (this.IsHandleCreated)
                this.Invalidate(true);
            //OnPropertyChanged(new PropertyChangedEventArgs("ColumnHeaderFont"));
        }
        /// 
        /// Called by StyleManager to notify control that style on manager has changed and that control should refresh its appearance if
        /// its style is controlled by StyleManager.
        /// 
        /// New active style.
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void StyleManagerStyleChanged(eDotNetBarStyle newStyle)
        {
            this.Invalidate(true);
            ResetCachedColorTableReference();
        }
        private void PaintHeaderBackground(Graphics g, Rectangle r)
        {
            Office2007ListViewColorTable ct = GetColorTable();
            DisplayHelp.FillRectangle(g, r, ct.ColumnBackground);
            using (Pen pen = new Pen(ct.Border))
            {
                g.DrawLine(pen, r.X, r.Bottom - 1, r.Right, r.Bottom - 1);
            }
        }
        private HeaderHandler m_HeaderHandler = null;
        protected override void OnHandleCreated(EventArgs e)
        {
            m_HeaderHandler = new HeaderHandler(this);
            base.OnHandleCreated(e);
        }
        protected override void OnHandleDestroyed(EventArgs e)
        {
            if (m_HeaderHandler != null)
            {
                m_HeaderHandler.ReleaseHandle();
                m_HeaderHandler = null;
            }
            base.OnHandleDestroyed(e);
        }
        /// 
        /// Resets internal Column Header handler. This method should be called after you change the View property
        /// at run-time. If your control is always in single view there is no need to call this method. This method
        /// will work only when controls handle has already been created.
        /// 
        public void ResetHeaderHandler()
        {
            if (!this.IsHandleCreated) return;
            if (m_HeaderHandler != null)
            {
                m_HeaderHandler.ReleaseHandle();
                m_HeaderHandler = null;
            }
            m_HeaderHandler = new HeaderHandler(this);
        }
        protected override void OnVisibleChanged(EventArgs e)
        {
            if (System.Environment.OSVersion.Version.Major < 6 && this.Visible)
                WinApi.PostMessage(this.Handle, 0x120, IntPtr.Zero, IntPtr.Zero);
            base.OnVisibleChanged(e);
        }
        /// 
        /// Resets the internal color table reference. This method is usually called automatically by 
        /// 
        public void ResetCachedColorTableReference()
        {
            m_ListViewColorTable = null;
            m_CheckBoxColorTable = null;
        }
        private Office2007ListViewColorTable m_ListViewColorTable = null;
        private Office2007ListViewColorTable GetColorTable()
        {
            if (m_ListViewColorTable == null)
            {
                Office2007Renderer r = this.GetRenderer() as Office2007Renderer;
                if (r != null)
                {
                    m_ListViewColorTable = r.ColorTable.ListViewEx;
                }
            }
            return m_ListViewColorTable;
        }
        private Office2007CheckBoxColorTable m_CheckBoxColorTable = null;
        private Office2007CheckBoxColorTable GetCheckBoxColorTable()
        {
            if (m_CheckBoxColorTable == null)
            {
                Office2007Renderer r = this.GetRenderer() as Office2007Renderer;
                if (r != null)
                {
                    m_CheckBoxColorTable = r.ColorTable.CheckBoxItem;
                }
            }
            return m_CheckBoxColorTable;
        }
        private void DrawColumnHeaderInternal(DrawListViewColumnHeaderEventArgs e)
        {
            Graphics g = e.Graphics;
            Rectangle r = e.Bounds;
            Office2007ListViewColorTable ct = GetColorTable();
            Color c1 = ct.ColumnBackground.Start;
            Color c2 = ct.ColumnBackground.End;
            if ((e.State & ListViewItemStates.Selected) == ListViewItemStates.Selected && !c2.IsEmpty)
            {
                Color csw = c1;
                c1 = c2;
                c2 = csw;
            }
            DisplayHelp.FillRectangle(g, r, c1, c2, ct.ColumnBackground.GradientAngle);
            using (Pen pen = new Pen(ct.Border))
            {
                g.DrawLine(pen, r.X, r.Bottom - 1, r.Right, r.Bottom - 1);
            }
            using (Pen pen = new Pen(ct.ColumnSeparator))
                g.DrawLine(pen, r.Right - 1, r.Y + 3, r.Right - 1, r.Bottom - 4);
            TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.SingleLine | TextFormatFlags.VerticalCenter | TextFormatFlags.WordEllipsis | TextFormatFlags.NoPrefix;
            switch (e.Header.TextAlign)
            {
                case HorizontalAlignment.Center:
                    flags |= TextFormatFlags.HorizontalCenter;
                    break;
                case HorizontalAlignment.Right:
                    flags |= TextFormatFlags.Right;
                    break;
            }
            if (e.Header.ImageList != null && (e.Header.ImageIndex >= 0 || e.Header.ImageKey != null && e.Header.ImageKey.Length > 0))
            {
                Image img = null;
                if (e.Header.ImageIndex >= 0)
                    img = e.Header.ImageList.Images[e.Header.ImageIndex];
                else
                    img = e.Header.ImageList.Images[e.Header.ImageKey];
                if (img != null)
                {
                    Rectangle imageRect = new Rectangle(r.X + 2, r.Y + (r.Height - img.Height) / 2, img.Width, img.Height);
                    if (this.RightToLeft == RightToLeft.Yes)
                    {
                        imageRect.X = r.Right - imageRect.Width - 2;
                        r.Width -= imageRect.Width + 2;
                    }
                    else
                    {
                        r.Width -= imageRect.Width;
                        r.X += imageRect.Width;
                    }
                    g.DrawImage(img, imageRect);
                }
            }
            Color foreColor = e.ForeColor;
            if (!ct.ColumnForeColor.IsEmpty)
                foreColor = ct.ColumnForeColor;
            DrawHeaderText(g, e.Font, foreColor, flags, e.Header.Text, r);
            //e.DrawText(flags);
        }
        protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
        {
            //DrawColumnHeaderInternal(e);   
            base.OnDrawColumnHeader(e);
        }
        private void DrawHeaderText(Graphics g, Font font, Color c, TextFormatFlags flags, string text, Rectangle r)
        {
            Size sz = TextRenderer.MeasureText(" ", font);
            int w = sz.Width;
            r.Inflate(-(w / 2), 0);
            TextRenderer.DrawText(g, text, font, r, c, flags);
        }
        private void DrawItemBackground(Graphics g, Rectangle r, ListViewItem item, ListViewItemStates state)
        {
            if (!this.Enabled) return;
            // Bug fix in ListView for this specific state
            if (state == 0 && item.Selected && this.View == View.Details && this.FullRowSelect && this.Focused)
                r.X++;
            if (!item.BackColor.IsEmpty)
            {
                using (SolidBrush brush = new SolidBrush(item.BackColor))
                {
                    g.FillRectangle(brush, r);
                }
            }
            bool selected = IsInState(state, ListViewItemStates.Selected) || state == 0 && item.Selected;
            if (selected)
            {
                Office2007ListViewColorTable ct = GetColorTable();
                // Draw the background for selected item.
                r.Height--;
                r.Width--;
                using (Pen pen = new Pen(ct.SelectionBorder))
                    g.DrawRectangle(pen, r);
                r.Height++;
                r.Width++;
                Rectangle ir = new Rectangle(r.X, r.Y + 1, r.Width, r.Height - 2);
                DisplayHelp.FillRectangle(g, ir, ct.SelectionBackground);
            }
            else if (IsInState(state, ListViewItemStates.Hot) && this.HotTracking)
            {
                Office2007Renderer rnd = this.GetRenderer() as Office2007Renderer;
                Office2007ButtonItemPainter.PaintBackground(g, rnd.ColorTable.ButtonItemColors[0].MouseOver, r, RoundRectangleShapeDescriptor.RectangleShape);
            }
            if (IsInState(state, ListViewItemStates.Focused) && (!IsInState(state, ListViewItemStates.Hot) && this.View != View.LargeIcon || selected))
            {
                Rectangle rFocus = item.Bounds;
                if (this.View == View.Details && !this.FullRowSelect || this.View == View.List)
                    rFocus = item.GetBounds(ItemBoundsPortion.Label);
                else if (this.View == View.Details && this.FullRowSelect)
                    rFocus = r;
                else if (this.View == View.SmallIcon)
                    rFocus = r;
                if (selected)
                {
                    rFocus.Y++;
                    rFocus.Height -= 2;
                }
                DrawFocusRectangle(g, rFocus, item);
            }
            else if (selected && this.View == View.Details && this.FullRowSelect && this.Focused) // Bug fix in ListView for this specific state
            {
                Rectangle rFocus = r;
                rFocus.Y++;
                rFocus.Height -= 2;
                Region oldClip = g.Clip;
                Rectangle rClip = rFocus;
                rClip.Width--;
                g.SetClip(rClip);
                DrawFocusRectangle(g, rFocus, item);
                g.Clip = oldClip;
            }
        }
        private bool IsInState(ListViewItemStates currentState, ListViewItemStates testState)
        {
            return ((currentState & testState) == testState);
        }
        protected override void OnDrawItem(DrawListViewItemEventArgs e)
        {
            if (e.State == 0 && this.View != View.List && this.View != View.Tile && this.View != View.SmallIcon && this.View != View.LargeIcon || this.View == View.Details)
            {
                base.OnDrawItem(e);
                return;
            }
            FixStateForHideSelection(e);
            Graphics g = e.Graphics;
            Rectangle r = e.Bounds;
            if (this.View == View.List)
                r = e.Item.GetBounds(ItemBoundsPortion.Label);
            else if (this.View == View.SmallIcon)
            {
                r = e.Item.GetBounds(ItemBoundsPortion.Label);
                //Size sz = TextDrawing.MeasureString(g, e.Item.Text, e.Item.Font);
                //sz.Width += 2;
                //if (sz.Width > r.Width)
                //    r.Width = sz.Width;
            }
            DrawItemBackground(g, r, e.Item, e.State);
            Color foreColor = e.Item.ForeColor;
            if (IsInState(e.State, ListViewItemStates.Selected) && this.Enabled)
            {
                Office2007ListViewColorTable ct = GetColorTable();
                if (!ct.SelectionForeColor.IsEmpty)
                    foreColor = ct.SelectionForeColor;
            }
            DrawListViewItem(g, e.Item, null, e.Item.Font, foreColor, e.State);
            base.OnDrawItem(e);
        }
        private bool HasImage(ListViewItem item)
        {
            if (item.ImageList != null && (item.ImageIndex >= 0 || item.ImageKey.Length > 0))
                return true;
            return false;
        }
        private Size m_CheckSignSize = new Size(13, 13);
        private void DrawListViewItem(Graphics g, ListViewItem item, ColumnHeader header, Font font, Color color, ListViewItemStates state)
        {
            bool hasImage = HasImage(item);
            // Draw Image if any
            if (hasImage && (header == null || header.Width > 4))
            {
                Rectangle rImage = item.GetBounds(ItemBoundsPortion.Icon);
                int index = item.ImageIndex;
                if (index < 0)
                    index = item.ImageList.Images.IndexOfKey(item.ImageKey);
                if (this.View != View.Details && this.View != View.List && this.StateImageList != null)
                    rImage.X += this.StateImageList.ImageSize.Width + 3;
                else if (this.View == View.SmallIcon && this.CheckBoxes && this.Groups.Count == 0)
                    rImage.X += this.SmallImageList.ImageSize.Width;
                else if (this.View == View.LargeIcon && (item.ImageList.ImageSize.Width < rImage.Width || item.ImageList.ImageSize.Height < rImage.Height))
                {
                    if (item.ImageList.ImageSize.Width < rImage.Width)
                        rImage.X += (rImage.Width - item.ImageList.ImageSize.Width) / 2;
                    if (item.ImageList.ImageSize.Height < rImage.Height)
                        rImage.Y += (rImage.Height - item.ImageList.ImageSize.Height) / 2;
                }
                Region oldClip = null;
                if (header != null && header.Width < rImage.Width)
                {
                    Rectangle rClip = rImage;
                    rClip.Width = header.Width;
                    oldClip = g.Clip;
                    g.SetClip(rClip);
                }
                if (rImage.Width > 2)
                {
                    g.DrawImage(item.ImageList.Images[index], rImage.Location); // item.ImageList.Draw(g, rImage.Location, index);
                }
                if (oldClip != null) g.Clip = oldClip;
            }
            //Console.WriteLine("{0} - {1} " ,DateTime.Now, item.SubItems[0].Text);
            // Draw text
            Rectangle rText = item.GetBounds(ItemBoundsPortion.Label);
            if (rText.Width > 2)
            {
                // Draw the item text for views other than the Details view.
                eTextFormat flags = eTextFormat.Left | eTextFormat.SingleLine | eTextFormat.NoPrefix;
                if (this.View == View.Tile && item.SubItems.Count > 1)
                    flags |= eTextFormat.Top;
                else
                    flags |= eTextFormat.VerticalCenter;
                if (this.View == View.LargeIcon)
                {
                    flags = eTextFormat.HorizontalCenter | eTextFormat.WordBreak | eTextFormat.EndEllipsis | eTextFormat.NoClipping;
                }
                else if (this.View == View.Details && header != null)
                {
                    flags |= eTextFormat.EndEllipsis;
                    if (header.TextAlign == HorizontalAlignment.Center)
                        flags |= eTextFormat.HorizontalCenter;
                    else if (header.TextAlign == HorizontalAlignment.Right)
                        flags |= eTextFormat.Right;
                    rText.X += 2;
                }
                else if (this.View == View.List || this.View == View.SmallIcon)
                    rText.X += 2;
                if (!BarFunctions.IsVista) rText.Inflate(0, 1);
                TextDrawing.DrawString(g, item.Text, font, color, rText, flags);
                if (this.View == View.Tile && item.SubItems.Count > 1)
                {
                    Size sz = TextDrawing.MeasureString(g, item.Text, font);
                    rText.Y += sz.Height;
                    rText.Height -= sz.Height;
                    Color c1 = item.SubItems[1].ForeColor;
                    if (!c1.IsEmpty && c1 != color)
                        color = c1;
                    else
                        color = SystemColors.ControlDarkDark;
                    TextDrawing.DrawString(g, item.SubItems[1].Text, font, color, rText, flags);
                }
            }
            if (this.View == View.Details || this.StateImageList != null)
            {
                if (this.StateImageList != null)
                {
                    if (item.StateImageIndex >= 0 && item.StateImageIndex < this.StateImageList.Images.Count)
                    {
                        Rectangle r = item.GetBounds(ItemBoundsPortion.Icon);
                        if (this.View == View.Details || this.View == View.List)
                            r.X -= 19;
                        else if (this.View == View.LargeIcon && r.Width > this.StateImageList.ImageSize.Width)
                        {
                            r.X += (r.Width - this.StateImageList.ImageSize.Width) / 2;
                            r.Y++;
                        }
                        else if (this.View == View.Tile && r.Height > this.StateImageList.ImageSize.Height)
                        {
                            r.Y += (r.Height - this.StateImageList.ImageSize.Height) / 2;
                            r.X++;
                        }
                        this.StateImageList.Draw(g, r.Location, item.StateImageIndex);
                    }
                }
            }
            if (this.CheckBoxes && (this.View == View.Details || this.View == View.List || this.View == View.SmallIcon || this.View == View.LargeIcon) && this.StateImageList == null)
            {
                Rectangle r = item.GetBounds(ItemBoundsPortion.Icon);
                if (this.View == View.LargeIcon)
                    r.X += 9;
                else if (this.View == View.List)
                    r.X -= 18;
                else if (this.View == View.SmallIcon && hasImage && this.Groups.Count > 0)
                    r.X -= 20;
                else if (this.View == View.SmallIcon)
                    r.X -= 3;
                else
                    r.X -= 21;
                Office2007CheckBoxItemPainter p = PainterFactory.CreateCheckBoxItemPainter(null);
                Office2007CheckBoxColorTable ctt = GetCheckBoxColorTable();
                Office2007CheckBoxStateColorTable ct = ctt.Default;
                if ((state & ListViewItemStates.Grayed) != 0 || !this.Enabled)
                    ct = ctt.Disabled;
                //else if ((state & ListViewItemStates.Hot) != 0)
                //    ct = ctt.MouseOver;
                p.PaintCheckBox(g, new Rectangle(r.X + 4, r.Y + (r.Height - m_CheckSignSize.Height) / 2, m_CheckSignSize.Width, m_CheckSignSize.Height),
                    ct, item.Checked ? CheckState.Checked : CheckState.Unchecked);
            }
        }
        protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e)
        {
            FixStateForHideSelection(e);
            Graphics g = e.Graphics;
            bool backgroundErased = false;
            //if (e.ItemState == 0 && this.View == View.Details && this.FullRowSelect) return; Can't do this can cause items not be displayed at all
            if (this.FullRowSelect && IsInState(e.ItemState, ListViewItemStates.Selected) && e.Header != null &&
                (e.Header.DisplayIndex == 0 || e.Bounds.X <= 0 && e.Header.DisplayIndex > 0 && this.Scrollable))
            {
                Rectangle r = e.Item.Bounds;
                if ((HasImage(e.Item) || e.Header.DisplayIndex != e.Header.Index) && e.Header.DisplayIndex == 0)
                {
                    Rectangle rLabel = e.Item.GetBounds(ItemBoundsPortion.Icon);
                    int w = Math.Min(e.Header.Width, (rLabel.Right - r.X) + 1);
                    r.Width -= w;
                    r.X += w;
                }
                DrawItemBackground(g, r, e.Item, e.ItemState);
                backgroundErased = true;
            }
            if (e.ColumnIndex == 0)
            {
                if (!(this.FullRowSelect && IsInState(e.ItemState, ListViewItemStates.Selected)))
                {
                    Rectangle r = e.Item.GetBounds(ItemBoundsPortion.Label);
                    //if (System.Environment.OSVersion.Version.Major < 6)
                    //    r.Height += 2;
                    //else
                    //    r.Height++;
                    DrawItemBackground(g, r, e.Item, e.ItemState);
                    backgroundErased = true;
                }
                Color foreColor = e.Item.ForeColor;
                Office2007ListViewColorTable ct = GetColorTable();
                if (IsInState(e.ItemState, ListViewItemStates.Selected) && !ct.SelectionForeColor.IsEmpty) foreColor = ct.SelectionForeColor;
                if (!this.Enabled) foreColor = _DisabledForeColor.IsEmpty ? SystemColors.ControlDark : _DisabledForeColor;
                DrawListViewItem(g, e.Item, e.Header, e.Item.Font, foreColor, e.ItemState);
                // This was added to address issue in Detail view where with row selected for first time, mouse over the second
                // column would erase the text in subsequent columns without them getting paint call so text was was visible
                if (backgroundErased && this.FullRowSelect && IsInState(e.ItemState, ListViewItemStates.Selected) && this.View == View.Details)
                {
                    // Paint SubItems
                    for (int i = 1; i < e.Item.SubItems.Count; i++)
                    {
                        System.Windows.Forms.ListViewItem.ListViewSubItem subItem = e.Item.SubItems[i];
                        Rectangle r = subItem.Bounds;
                        if (r.IntersectsWith(this.DisplayRectangle))
                            PaintSubItem(g, subItem, r, e.ItemState, (i < this.Columns.Count ? this.Columns[i] : null), e.Item.BackColor, i);
                    }
                }
                //int start = m_FirstVisibleColumnIndex;
                //if (start == 0) start++;
                // Paint SubItems
                //for (int i = start; i < e.Item.SubItems.Count; i++)
                //{
                //    System.Windows.Forms.ListViewItem.ListViewSubItem subItem = e.Item.SubItems[i];
                //    Rectangle r = subItem.Bounds;
                //    if (r.IntersectsWith(this.DisplayRectangle))
                //        PaintSubItem(g, subItem, r, e.ItemState, (i < this.Columns.Count ? this.Columns[i] : null), e.Item.BackColor);
                //}
            }
            else
            {
                if (this.FullRowSelect && IsInState(e.ItemState, ListViewItemStates.Selected) && e.Header.DisplayIndex != e.Header.Index)
                {
                    Rectangle r = e.Bounds;
                    DrawItemBackground(g, r, e.Item, e.ItemState);
                    backgroundErased = true;
                }
                if (e.Header.Width > 0)
                    PaintSubItem(g, e.SubItem, e.Bounds, e.ItemState, this.Columns[e.ColumnIndex], e.Item.BackColor, e.ColumnIndex);
            }
            base.OnDrawSubItem(e);
        }
        private Color _DisabledForeColor = Color.Empty;
        /// 
        /// Gets or sets the item foreground color when control or item is disabled. By default SystemColors.Dark is used.
        /// 
        [Category("Appearance"), Description("Indicates item foreground color when control or item is disabled.")]
        public Color DisabledForeColor
        {
            get { return _DisabledForeColor; }
            set { _DisabledForeColor = value; }
        }
        /// 
        /// Gets whether property should be serialized by VS.NET designer.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeDisabledForeColor()
        {
            return !_DisabledForeColor.IsEmpty;
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetDisabledForeColor()
        {
            DisabledForeColor = Color.Empty;
        }
        //[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        //public new bool HideSelection
        //{
        //    get { return base.HideSelection; }
        //    set { base.HideSelection = false; }
        //}
        //private int m_FirstVisibleColumnIndex = 0;
        //private void UpdateFirstVisibleColumnIndex()
        //{
        //    m_FirstVisibleColumnIndex = 0;
        //    if (this.View == View.Details && this.Columns.Count > 0 && this.Items.Count>0)
        //    {
        //        ListViewItem item = this.Items[0];
        //        if (item.Bounds.X < 0)
        //        {
        //            int x = item.Bounds.X;
        //            IList list = GetOrderedColumnList();
        //            for (int i = 0; i < list.Count; i++)
        //            {
        //                ColumnHeader h = list[i] as ColumnHeader;
        //                if (x + h.Width > 0)
        //                {
        //                    m_FirstVisibleColumnIndex = i;
        //                    break;
        //                }
        //                else
        //                    x += h.Width;
        //            }
        //        }
        //    }
        //}
        private IList GetOrderedColumnList()
        {
            IList columns = this.Columns;
            if (this.AllowColumnReorder)
            {
                ArrayList ca = new ArrayList(this.Columns);
                foreach (ColumnHeader h in columns)
                {
                    if (h.DisplayIndex < 0) continue;
                    ca[h.DisplayIndex] = h;
                }
                columns = ca;
            }
            return columns;
        }
        private void PaintSubItem(Graphics g, ListViewItem.ListViewSubItem subitem, Rectangle r, ListViewItemStates state, ColumnHeader header, Color itemBackColor, int columnIndex)
        {
            if (!IsInState(state, ListViewItemStates.Selected) && this.Enabled)
            {
                Rectangle rFill = r;
                //rFill.Height++;
                if (!subitem.BackColor.IsEmpty /*&& !(subitem.BackColor == this.BackColor && !itemBackColor.IsEmpty)*/)
                {
                    using (SolidBrush brush = new SolidBrush(subitem.BackColor))
                        g.FillRectangle(brush, rFill);
                }
                else if (!itemBackColor.IsEmpty)
                {
                    using (SolidBrush brush = new SolidBrush(itemBackColor))
                        g.FillRectangle(brush, rFill);
                }
            }
            eTextFormat flags = eTextFormat.Left | eTextFormat.SingleLine | eTextFormat.VerticalCenter | eTextFormat.EndEllipsis | eTextFormat.NoClipping | eTextFormat.NoPrefix;
            if (header != null)
            {
                if (header.TextAlign == HorizontalAlignment.Center)
                    flags |= eTextFormat.HorizontalCenter;
                else if (header.TextAlign == HorizontalAlignment.Right)
                    flags |= eTextFormat.Right;
            }
            Color foreColor = subitem.ForeColor;
            if (IsInState(state, ListViewItemStates.Selected) && this.Enabled && (columnIndex == 0 || this.FullRowSelect))
            {
                Office2007ListViewColorTable ct = GetColorTable();
                if (!ct.SelectionForeColor.IsEmpty)
                    foreColor = ct.SelectionForeColor;
            }
            if (!this.Enabled) foreColor = _DisabledForeColor.IsEmpty ? SystemColors.ControlDark : _DisabledForeColor;
            Rectangle rText = Rectangle.Inflate(r, -2, BarFunctions.IsVista ? 0 : 1); // Rectangle.Inflate(r, -sz.Width, 0);
            TextDrawing.DrawString(g, subitem.Text, subitem.Font, foreColor, rText, flags);
            //Console.WriteLine("{0}-Sub {1} {2}",DateTime.Now, subitem.Text,rText);
        }
        private void DrawFocusRectangle(Graphics g, Rectangle r, ListViewItem item)
        {
            if (_FocusCuesEnabled)
                ControlPaint.DrawFocusRectangle(g, r, item.ForeColor, item.BackColor);
        }
        private bool _FocusCuesEnabled = true;
        /// 
        /// Gets or sets whether control displays focus cues when focused.
        /// 
        [DefaultValue(true), Category("Behavior"), Description("Indicates whether control displays focus cues when focused.")]
        public virtual bool FocusCuesEnabled
        {
            get { return _FocusCuesEnabled; }
            set
            {
                _FocusCuesEnabled = value;
                if (this.Focused) this.Invalidate();
            }
        }
        private Rectangle UpdateBounds(Rectangle originalBounds, bool drawText, ListViewItem item)
        {
            Rectangle r = originalBounds;
            if (this.View == View.Details)
            {
                if (!this.FullRowSelect && (item.SubItems.Count > 0))
                {
                    ListViewItem.ListViewSubItem subItem = item.SubItems[0];
                    Size textSize = TextRenderer.MeasureText(subItem.Text, subItem.Font);
                    r = new Rectangle(originalBounds.X, originalBounds.Y, textSize.Width, textSize.Height);
                    r.X += 4;
                    r.Width++;
                }
                else
                {
                    r.X += 4;
                    r.Width -= 4;
                }
                if (drawText)
                {
                    r.X--;
                }
            }
            return r;
        }
        private Point m_MouseDown = Point.Empty;
        protected override void OnMouseDown(MouseEventArgs e)
        {
            m_MouseDown = new Point(e.X, e.Y);
            if (this.View == View.LargeIcon && this.CheckBoxes)
            {
                ListViewHitTestInfo info = HitTest(m_MouseDown);
                if (info.Item == null)
                    info = HitTest(new Point(e.X + 9, e.Y));
                if (info.Item != null)
                {
                    Rectangle r = info.Item.GetBounds(ItemBoundsPortion.Icon);
                    r.X += 9;
                    r = new Rectangle(r.X + 4, r.Y + (r.Height - m_CheckSignSize.Height) / 2, m_CheckSignSize.Width-4,
                        m_CheckSignSize.Height);
                    if (r.Contains(m_MouseDown))
                        info.Item.Checked = !info.Item.Checked;
                }
            }
            base.OnMouseDown(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (this.View == View.Details && this.FullRowSelect && !this.IsDisposed && !this.CheckBoxes)
            {
                ListViewItem clickedItem = GetItemAt(5, e.Y);
                ListViewItem mouseDownItem = GetItemAt(5, m_MouseDown.Y);
                if (clickedItem != null && clickedItem == mouseDownItem)
                {
                    //clickedItem.Selected = true; // There was a bug when this is executed that did not allow an item to be Ctrl+Mouse Click deselected
                    if (clickedItem.Selected)
                        clickedItem.Focused = true;
                }
            }
        }
        private bool m_FirstMouseEnter = true;
        protected override void OnMouseEnter(EventArgs e)
        {
            if (m_FirstMouseEnter)
            {
                this.Refresh();
                m_FirstMouseEnter = false;
            }
            base.OnMouseEnter(e);
        }
        protected override void OnLostFocus(EventArgs e)
        {
            if (this.HideSelection)
            {
                if (!this.VirtualMode && this.SelectedItems.Count > 0)
                {
                    foreach (ListViewItem item in this.SelectedItems)
                    {
                        Rectangle r = item.Bounds;
                        if (this.View == View.Details)
                        {
                            r.X = 0;
                            r.Width = this.Width;
                        }
                        else if (this.View == View.LargeIcon)
                        {
                            r.Inflate(32, 32);
                        }
                        this.Invalidate(r);
                    }
                }
            }
            base.OnLostFocus(e);
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new bool OwnerDraw
        {
            get { return base.OwnerDraw; }
            set { base.OwnerDraw = value; }
        }
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        private struct NMHDR
        {
            public IntPtr hwndFrom;
            public IntPtr idFrom;
            public int code;
        }
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        private struct NMCUSTOMDRAW
        {
            public NMHDR nmcd;
            public int dwDrawStage;
            public IntPtr hdc;
            public WinApi.RECT rc;
            public IntPtr dwItemSpec;
            public int uItemState;
            public IntPtr lItemlParam;
        }
        protected override void WndProc(ref Message m)
        {
            if (m_NCPainter != null)
            {
                bool callBase = m_NCPainter.WndProc(ref m);
                if (callBase)
                    base.WndProc(ref m);
            }
            else
            {
                base.WndProc(ref m);
            }
            //if (m.Msg == (int)WinApi.WindowsMessages.WM_HSCROLL)
            //{
            //    UpdateFirstVisibleColumnIndex();
            //}
        }
        private Rendering.BaseRenderer m_DefaultRenderer = null;
        private Rendering.BaseRenderer m_Renderer = null;
        private eRenderMode m_RenderMode = eRenderMode.Global;
        /// 
        /// Returns the renderer control will be rendered with.
        /// 
        /// The current renderer.
        public virtual Rendering.BaseRenderer GetRenderer()
        {
            if (m_RenderMode == eRenderMode.Global && Rendering.GlobalManager.Renderer != null)
                return Rendering.GlobalManager.Renderer;
            else if (m_RenderMode == eRenderMode.Custom && m_Renderer != null)
                return m_Renderer;
            if (m_DefaultRenderer == null)
                m_DefaultRenderer = new Rendering.Office2007Renderer();
            return m_DefaultRenderer;
        }
        /// 
        /// Gets or sets the redering mode used by control. Default value is eRenderMode.Global which means that static GlobalManager.Renderer is used. If set to Custom then Renderer property must
        /// also be set to the custom renderer that will be used.
        /// 
        [Browsable(false), DefaultValue(eRenderMode.Global)]
        public eRenderMode RenderMode
        {
            get { return m_RenderMode; }
            set
            {
                if (m_RenderMode != value)
                {
                    m_RenderMode = value;
                    m_ListViewColorTable = null;
                    this.Invalidate(true);
                }
            }
        }
        /// 
        /// Gets or sets the custom renderer used by the items on this control. RenderMode property must also be set to eRenderMode.Custom in order renderer
        /// specified here to be used.
        /// 
        [Browsable(false), DefaultValue(null)]
        public DevComponents.DotNetBar.Rendering.BaseRenderer Renderer
        {
            get
            {
                return m_Renderer;
            }
            set
            {
                m_Renderer = value;
                m_ListViewColorTable = null;
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new BorderStyle BorderStyle
        {
            get { return base.BorderStyle; }
            set { }
        }
        private ElementStyle GetBorderStyle()
        {
            m_BorderStyle.SetColorScheme(this.GetColorScheme());
            bool disposeStyle = false;
            return ElementStyleDisplay.GetElementStyle(m_BorderStyle,out disposeStyle);
        }
        /// 
        /// Specifies the control border style. Default value has Class property set so the system style for the control is used.
        /// 
        [Browsable(true), Category("Style"), Description("Specifies the control border style. Default value has Class property set so the system style for the control is used."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ElementStyle Border
        {
            get { return m_BorderStyle; }
        }
        private void BorderStyle_StyleChanged(object sender, EventArgs e)
        {
            if (!BarFunctions.IsHandleValid(this)) return;
            const int RDW_INVALIDATE = 0x0001;
            const int RDW_FRAME = 0x0400;
            NativeFunctions.RECT r = new NativeFunctions.RECT(0, 0, this.Width, this.Height);
            NativeFunctions.RedrawWindow(this.Handle, ref r, IntPtr.Zero, RDW_INVALIDATE | RDW_FRAME);
        }
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams p = base.CreateParams;
                p.ExStyle = p.ExStyle & ~(p.ExStyle & 0x200);
                return p;
            }
        }
        #endregion
        #region INonClientControl Members
        void INonClientControl.BaseWndProc(ref Message m)
        {
            base.WndProc(ref m);
        }
        ItemPaintArgs INonClientControl.GetItemPaintArgs(System.Drawing.Graphics g)
        {
            ItemPaintArgs pa = new ItemPaintArgs(this as IOwner, this, g, GetColorScheme());
            pa.Renderer = this.GetRenderer();
            pa.DesignerSelection = false; // m_DesignerSelection;
            pa.GlassEnabled = !this.DesignMode && WinApi.IsGlassEnabled;
            return pa;
        }
        ElementStyle INonClientControl.BorderStyle
        {
            get { return GetBorderStyle(); }
        }
        void INonClientControl.PaintBackground(PaintEventArgs e)
        {
            //if (this.Parent == null) return;
            //Type t = typeof(Control);
            //MethodInfo mi = t.GetMethod("PaintTransparentBackground", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(PaintEventArgs), typeof(Rectangle) }, null);
            //if (mi != null)
            //{
            //    mi.Invoke(this, new object[] { e, new Rectangle(0, 0, this.Width, this.Height) });
            //}
        }
        private ColorScheme m_ColorScheme = null;
        /// 
        /// Returns the color scheme used by control. Color scheme for Office2007 style will be retrived from the current renderer instead of
        /// local color scheme referenced by ColorScheme property.
        /// 
        /// An instance of ColorScheme object.
        protected virtual ColorScheme GetColorScheme()
        {
            BaseRenderer r = GetRenderer();
            if (r is Office2007Renderer)
                return ((Office2007Renderer)r).ColorTable.LegacyColors;
            if (m_ColorScheme == null)
                m_ColorScheme = new ColorScheme(eDotNetBarStyle.Office2007);
            return m_ColorScheme;
        }
        IntPtr INonClientControl.Handle
        {
            get { return this.Handle; }
        }
        int INonClientControl.Width
        {
            get { return this.Width; }
        }
        int INonClientControl.Height
        {
            get { return this.Height; }
        }
        bool INonClientControl.IsHandleCreated
        {
            get { return this.IsHandleCreated; }
        }
        Point INonClientControl.PointToScreen(Point client)
        {
            return this.PointToScreen(client);
        }
        Color INonClientControl.BackColor
        {
            get { return this.BackColor; }
        }
        void INonClientControl.AdjustClientRectangle(ref Rectangle r) { }
        void INonClientControl.AdjustBorderRectangle(ref Rectangle r) { }
        void INonClientControl.RenderNonClient(Graphics g) { }
        private Color _DisabledBackColor = Color.Empty;
        /// 
        /// Specifies back color when Enabled=false
        /// 
        [Browsable(false), Category("Appearance"), Description("Specifies back color when Enabled=false")]
        public Color DisabledBackColor
        {
            get { return _DisabledBackColor; }
            set
            {
                _DisabledBackColor = value;
                if (!Enabled) this.Invalidate();
            }
        }
        #endregion
        #region HeaderNativeWindowHandler
        private class HeaderHandler : NativeWindow
        {
            private ListViewEx m_Parent = null;
            private bool m_MouseDown = false;
            private Point m_MouseDownPoint = Point.Empty;
            public HeaderHandler(ListViewEx parent)
            {
                m_Parent = parent;
                IntPtr h = new IntPtr(WinApi.SendMessage(parent.Handle, (0x1000 + 31), IntPtr.Zero, IntPtr.Zero));
                if (h != IntPtr.Zero)
                    AssignHandle(h);
            }
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == (int)WinApi.WindowsMessages.WM_PAINT)
                {
                    WinApi.PAINTSTRUCT ps = new WinApi.PAINTSTRUCT();
                    IntPtr hdc = WinApi.BeginPaint(m.HWnd, ref ps);
                    try
                    {
                        Graphics g = Graphics.FromHdc(hdc);
                        try
                        {
                            WinApi.RECT r = new WinApi.RECT();
                            WinApi.GetWindowRect(m.HWnd, ref r);
                            Rectangle rc = new Rectangle(0, 0, r.Width, r.Height);
                            using (BufferedBitmap bb = new BufferedBitmap(hdc, rc))
                            {
                                m_Parent.PaintHeaderBackground(bb.Graphics, rc);
                                IList columns = m_Parent.GetOrderedColumnList();
                                int x = 0;
                                foreach (ColumnHeader h in columns)
                                {
                                    Rectangle hr = new Rectangle(x, 0, h.Width, r.Height);
                                    ListViewItemStates state = ListViewItemStates.ShowKeyboardCues;
                                    if (m_MouseDown && hr.Contains(m_MouseDownPoint))
                                    {
                                        Rectangle rt = hr;
                                        rt.Inflate(-6, 0);
                                        if (rt.Contains(m_MouseDownPoint))
                                            state |= ListViewItemStates.Selected;
                                    }
                                    m_Parent.DrawColumnHeaderInternal(new DrawListViewColumnHeaderEventArgs(bb.Graphics, hr, h.DisplayIndex, h,
                                        state, SystemColors.ControlText, Color.Empty, m_Parent.ColumnHeaderFont ?? m_Parent.Font));
                                    x += h.Width;
                                }
                                bb.Render(g);
                            }
                        }
                        finally
                        {
                            g.Dispose();
                        }
                    }
                    finally
                    {
                        WinApi.EndPaint(m.HWnd, ref ps);
                    }
                    return;
                }
                else if (m.Msg == (int)WinApi.WindowsMessages.WM_LBUTTONDOWN)
                {
                    if (m_Parent.HeaderStyle == ColumnHeaderStyle.Clickable)
                    {
                        m_MouseDown = true;
                        m_MouseDownPoint = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam));
                        WinApi.RedrawWindow(m.HWnd, IntPtr.Zero, IntPtr.Zero, WinApi.RedrawWindowFlags.RDW_INVALIDATE);
                    }
                }
                else if (m.Msg == (int)WinApi.WindowsMessages.WM_LBUTTONUP)
                {
                    m_MouseDown = false;
                    m_MouseDownPoint = Point.Empty;
                }
                else if (m.Msg == (int)WinApi.WindowsMessages.WM_MOUSEMOVE && m_MouseDown)
                {
                    m_MouseDownPoint = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam));
                }
                base.WndProc(ref m);
            }
        }
        #endregion
        #region Hide-Selection ListView Bug Hacking
        bool _IsItemInitialized = false;
        bool _IsSubItemInitialized = false;
        FieldInfo _ItemStateField = null;
        FieldInfo _SubItemStateField = null;
        private void FixStateForHideSelection(DrawListViewItemEventArgs e)
        {
            if (HideSelection) return;
            if (!this._IsItemInitialized)
            {
                _ItemStateField = e.GetType().GetField("state",BindingFlags.NonPublic | BindingFlags.Instance);
                _IsItemInitialized = true;
            }
            if (_ItemStateField != null)
            {
                UpdateStateBit(e, _ItemStateField, e.Item.Selected,e.State);
            }
        }
        private void FixStateForHideSelection(DrawListViewSubItemEventArgs e)
        {
            if (HideSelection) return;
            if (!_IsSubItemInitialized)
            {
                _SubItemStateField =e.GetType().GetField("itemState", BindingFlags.NonPublic |BindingFlags.Instance);
                _IsSubItemInitialized = true;
            }
            if (_SubItemStateField != null)
            {
                UpdateStateBit(e, _SubItemStateField,e.Item.Selected, e.ItemState);
            }
        }
        private void UpdateStateBit(object o, FieldInfo f, bool itemSelected, ListViewItemStates currentState)
        {
            bool stateSelected = (currentState & ListViewItemStates.Selected) != 0;
            if (itemSelected != stateSelected)
            {
                ListViewItemStates newState = currentState;
                if (itemSelected)
                {
                    newState |= ListViewItemStates.Selected;
                }
                else
                {
                    newState &= ~(ListViewItemStates.Selected);
                }
                try
                {
                    f.SetValue(o, newState);
                }
                catch { }
            }
        }
        #endregion
    }
}
#endif