/// <summary> /// Draw one cell of the header /// </summary> /// <param name="g"></param> /// <param name="columnIndex"></param> /// <param name="itemState"></param> protected void CustomDrawHeaderCell(Graphics g, int columnIndex, int itemState) { Rectangle r = this.GetItemRect(columnIndex); OLVColumn column = this.ListView.GetColumn(columnIndex); const int CDIS_SELECTED = 1; bool isPressed = ((itemState & CDIS_SELECTED) == CDIS_SELECTED); // Calculate which style should be used for the header HeaderStateStyle stateStyle = this.CalculateStyle(column, columnIndex == this.ColumnIndexUnderCursor, isPressed); // Draw the background if (this.ListView.HeaderUsesThemes && VisualStyleRenderer.IsSupported && VisualStyleRenderer.IsElementDefined(VisualStyleElement.Header.Item.Normal)) { this.DrawThemedBackground(g, r, columnIndex, isPressed); } else { this.DrawUnthemedBackground(g, r, columnIndex, isPressed, stateStyle); } // Draw the sort indicator if this column has one if (this.HasSortIndicator(column)) { if (this.ListView.HeaderUsesThemes && VisualStyleRenderer.IsSupported && VisualStyleRenderer.IsElementDefined(VisualStyleElement.Header.SortArrow.SortedUp)) { this.DrawThemedSortIndicator(g, r); } else { r = this.DrawUnthemedSortIndicator(g, r); } } // Finally draw the text this.DrawHeaderImageAndText(g, r, column, stateStyle); }
private bool NeedsCustomDraw(HeaderStateStyle style) { if (style == null) { return(false); } // If we want fancy colors or frames, we have to custom draw. Oddly enough, we // can handle font changes without custom drawing. if (!style.BackColor.IsEmpty) { return(true); } if (style.FrameWidth > 0f && !style.FrameColor.IsEmpty) { return(true); } return(!style.ForeColor.IsEmpty && style.ForeColor != Color.Black); }
/// <summary> /// What font should be used to draw the header text? /// </summary> /// <param name="column"></param> /// <param name="isHot"></param> /// <param name="isPressed"></param> /// <returns></returns> protected Font CalculateFont(OLVColumn column, bool isHot, bool isPressed) { HeaderStateStyle stateStyle = this.CalculateStyle(column, isHot, isPressed); return(stateStyle.Font ?? this.ListView.Font); }
/// <summary> /// Draw the header's image and text /// </summary> /// <param name="g"></param> /// <param name="r"></param> /// <param name="column"></param> /// <param name="stateStyle"></param> protected void DrawHeaderImageAndText(Graphics g, Rectangle r, OLVColumn column, HeaderStateStyle stateStyle) { TextFormatFlags flags = this.TextFormatFlags; flags |= TextFormatFlags.VerticalCenter; if (column.HeaderTextAlign == HorizontalAlignment.Center) { flags |= TextFormatFlags.HorizontalCenter; } if (column.HeaderTextAlign == HorizontalAlignment.Right) { flags |= TextFormatFlags.Right; } Font f = this.ListView.HeaderUsesThemes ? this.ListView.Font : stateStyle.Font ?? this.ListView.Font; Color color = this.ListView.HeaderUsesThemes ? Color.Black : stateStyle.ForeColor; if (color.IsEmpty) { color = Color.Black; } // Tweak the text rectangle a little to improve aethestics r.Inflate(-3, 0); r.Y -= 2; Rectangle textRect = r; const int imageTextGap = 3; if (column.IsHeaderVertical) { try { // Create a matrix transformation that will rotate the text 90 degrees vertically // AND place the text in the middle of where it was previously. [Think of tipping // a box over by its bottom left edge -- you have to move it back a bit so it's // in the same place as it started] Matrix m = new Matrix(); m.RotateAt(-90, new Point(r.X, r.Bottom)); m.Translate(0, r.Height); g.Transform = m; StringFormat fmt = new StringFormat(StringFormatFlags.NoWrap); fmt.Alignment = StringAlignment.Near; fmt.LineAlignment = column.HeaderTextAlignAsStringAlignment; //fmt.Trimming = StringTrimming.EllipsisCharacter; // The drawing is rotated 90 degrees, so switch our text boundaries textRect.Width = r.Height; textRect.Height = r.Width; g.DrawString(column.Text, f, new SolidBrush(color), textRect, fmt); } finally { g.ResetTransform(); } } else { // Does the column have a header image and is there space for it? if (column.HasHeaderImage && r.Width > column.ImageList.ImageSize.Width * 2) { textRect.X += (column.ImageList.ImageSize.Width + imageTextGap); textRect.Width -= (column.ImageList.ImageSize.Width + imageTextGap); Size textSize = TextRenderer.MeasureText(g, column.Text, f, textRect.Size, flags); int imageY = r.Top + ((r.Height - column.ImageList.ImageSize.Height) / 2); int imageX = textRect.Left; if (column.HeaderTextAlign == HorizontalAlignment.Center) { imageX = textRect.Left + ((textRect.Width - textSize.Width) / 2); } if (column.HeaderTextAlign == HorizontalAlignment.Right) { imageX = textRect.Right - textSize.Width; } imageX -= (column.ImageList.ImageSize.Width + imageTextGap); column.ImageList.Draw(g, imageX, imageY, column.ImageList.Images.IndexOfKey(column.HeaderImageKey)); } TextRenderer.DrawText(g, column.Text, f, textRect, color, Color.Transparent, flags); } }
/// <summary> /// Draw a background for the header, without using Themes. /// </summary> /// <param name="g"></param> /// <param name="r"></param> /// <param name="columnIndex"></param> /// <param name="isSelected"></param> /// <param name="stateStyle"></param> protected void DrawUnthemedBackground(Graphics g, Rectangle r, int columnIndex, bool isSelected, HeaderStateStyle stateStyle) { if (stateStyle.BackColor.IsEmpty) { // I know we're supposed to be drawing the unthemed background, but let's just see if we // can draw something more interesting than the dull raised block if (VisualStyleRenderer.IsSupported && VisualStyleRenderer.IsElementDefined(VisualStyleElement.Header.Item.Normal)) { this.DrawThemedBackground(g, r, columnIndex, isSelected); } else { ControlPaint.DrawBorder3D(g, r, Border3DStyle.RaisedInner); } } else { using (Brush b = new SolidBrush(stateStyle.BackColor)) g.FillRectangle(b, r); } // Draw the frame if the style asks for one if (!stateStyle.FrameColor.IsEmpty && stateStyle.FrameWidth > 0f) { RectangleF r2 = r; r2.Inflate(-stateStyle.FrameWidth, -stateStyle.FrameWidth); g.DrawRectangle(new Pen(stateStyle.FrameColor, stateStyle.FrameWidth), r2.X, r2.Y, r2.Width, r2.Height); } }
/// <summary> /// Draw the header's image and text /// </summary> /// <param name="g"></param> /// <param name="r"></param> /// <param name="column"></param> /// <param name="stateStyle"></param> protected void DrawHeaderImageAndText(Graphics g, Rectangle r, OLVColumn column, HeaderStateStyle stateStyle) { TextFormatFlags flags = this.TextFormatFlags; flags |= TextFormatFlags.VerticalCenter; if (column.HeaderTextAlign == HorizontalAlignment.Center) flags |= TextFormatFlags.HorizontalCenter; if (column.HeaderTextAlign == HorizontalAlignment.Right) flags |= TextFormatFlags.Right; Font f = this.ListView.HeaderUsesThemes ? this.ListView.Font : stateStyle.Font ?? this.ListView.Font; Color color = this.ListView.HeaderUsesThemes ? Color.Black : stateStyle.ForeColor; if (color.IsEmpty) color = Color.Black; // Tweak the text rectangle a little to improve aethestics r.Inflate(-3, 0); r.Y -= 2; Rectangle textRect = r; const int imageTextGap = 3; if (column.IsHeaderVertical) { try { // Create a matrix transformation that will rotate the text 90 degrees vertically // AND place the text in the middle of where it was previously. [Think of tipping // a box over by its bottom left edge -- you have to move it back a bit so it's // in the same place as it started] Matrix m = new Matrix(); m.RotateAt(-90, new Point(r.X, r.Bottom)); m.Translate(0, r.Height); g.Transform = m; StringFormat fmt = new StringFormat(StringFormatFlags.NoWrap); fmt.Alignment = StringAlignment.Near; fmt.LineAlignment = column.HeaderTextAlignAsStringAlignment; //fmt.Trimming = StringTrimming.EllipsisCharacter; // The drawing is rotated 90 degrees, so switch our text boundaries textRect.Width = r.Height; textRect.Height = r.Width; g.DrawString(column.Text, f, new SolidBrush(color), textRect, fmt); } finally { g.ResetTransform(); } } else { // Does the column have a header image and is there space for it? if (column.HasHeaderImage && r.Width > column.ImageList.ImageSize.Width * 2) { textRect.X += (column.ImageList.ImageSize.Width + imageTextGap); textRect.Width -= (column.ImageList.ImageSize.Width + imageTextGap); Size textSize = TextRenderer.MeasureText(g, column.Text, f, textRect.Size, flags); int imageY = r.Top + ((r.Height - column.ImageList.ImageSize.Height) / 2); int imageX = textRect.Left; if (column.HeaderTextAlign == HorizontalAlignment.Center) imageX = textRect.Left + ((textRect.Width - textSize.Width) / 2); if (column.HeaderTextAlign == HorizontalAlignment.Right) imageX = textRect.Right - textSize.Width; imageX -= (column.ImageList.ImageSize.Width + imageTextGap); column.ImageList.Draw(g, imageX, imageY, column.ImageList.Images.IndexOfKey(column.HeaderImageKey)); } TextRenderer.DrawText(g, column.Text, f, textRect, color, Color.Transparent, flags); } }
/// <summary> /// Draw a background for the header, without using Themes. /// </summary> /// <param name="g"></param> /// <param name="r"></param> /// <param name="columnIndex"></param> /// <param name="isSelected"></param> /// <param name="stateStyle"></param> protected void DrawUnthemedBackground(Graphics g, Rectangle r, int columnIndex, bool isSelected, HeaderStateStyle stateStyle) { if (stateStyle.BackColor.IsEmpty) // I know we're supposed to be drawing the unthemed background, but let's just see if we // can draw something more interesting than the dull raised block if (VisualStyleRenderer.IsSupported && VisualStyleRenderer.IsElementDefined(VisualStyleElement.Header.Item.Normal)) this.DrawThemedBackground(g, r, columnIndex, isSelected); else ControlPaint.DrawBorder3D(g, r, Border3DStyle.RaisedInner); else { using (Brush b = new SolidBrush(stateStyle.BackColor)) g.FillRectangle(b, r); } // Draw the frame if the style asks for one if (!stateStyle.FrameColor.IsEmpty && stateStyle.FrameWidth > 0f) { RectangleF r2 = r; r2.Inflate(-stateStyle.FrameWidth, -stateStyle.FrameWidth); g.DrawRectangle(new Pen(stateStyle.FrameColor, stateStyle.FrameWidth), r2.X, r2.Y, r2.Width, r2.Height); } }
private bool NeedsCustomDraw(HeaderStateStyle style) { if (style == null) return false; // If we want fancy colors or frames, we have to custom draw. Oddly enough, we // can handle font changes without custom drawing. if (!style.BackColor.IsEmpty) return true; if (style.FrameWidth > 0f && !style.FrameColor.IsEmpty) return true; return (!style.ForeColor.IsEmpty && style.ForeColor != Color.Black); }