#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