void DoHeaderCustomDrawing(ref Message m) { NMCUSTOMDRAW nmcd = (NMCUSTOMDRAW)m.GetLParam(typeof(NMCUSTOMDRAW)); using (Graphics g = Graphics.FromHdc(nmcd.hdc)) { Rectangle rc = GetHeaderCtrlRect(); rc = GetHeaderItemRect(nmcd.dwItemSpec); int itemRight = rc.Left + rc.Width; g.FillRectangle(new SolidBrush(SystemColors.ScrollBar), rc.Left, rc.Top, rc.Width, rc.Height); if (nmcd.dwItemSpec == PressedHeaderItem && !IsCursorOnDivider() && Tracking == false) { PressedHeaderItem = -1; rc.Inflate(-1, -1); g.FillRectangle(new SolidBrush(ColorUtil.VSNetPressedColor), rc.Left, rc.Top, rc.Width, rc.Height); } else { ControlPaint.DrawBorder3D(g, rc.Left, rc.Top, rc.Width, rc.Height - 1, Border3DStyle.RaisedInner, Border3DSide.All); } string text = GetHeaderItemText(nmcd.dwItemSpec); Debug.WriteLine(text); Size textSize = TextUtil.GetTextSize(g, text, Font); int gap = 4; Point pos = new Point(rc.Left + gap, rc.Top + ((rc.Height - textSize.Height) / 2)); int headerImageIndex; if (headerIconsList != null && HasHeaderImage(nmcd.dwItemSpec, out headerImageIndex)) { if (headerImageIndex != -1) { Image image = headerImageList.Images[headerImageIndex]; if (image != null) { g.DrawImage(headerImageList.Images[headerImageIndex], rc.Left + gap, rc.Top); pos.X += IMAGE_WIDTH; rc.Width = rc.Width - IMAGE_WIDTH; } } } // Draw arrow glyph if (nmcd.dwItemSpec == lastSortedColumn) { int Left = pos.X + 2; Left += textSize.Width + TEXT_TO_ARROW_GAP; Rectangle arrowRect = new Rectangle(Left, rc.Top, ARROW_WIDTH, rc.Height); if (itemRight >= (Left + ARROW_WIDTH + 4)) { if (Sorting == SortOrder.Ascending || Sorting == SortOrder.None) { DrawUpArrow(g, arrowRect); } else { DrawDownArrow(g, arrowRect); } } } // I use the Windows API instead of the Graphics object to draw the string // because the Graphics object draws ellipes without living blank spaces in between // the DrawText API adds those blank spaces in between int ellipsingTringgering = 8; Rectangle drawRect = new Rectangle(pos.X + 2, pos.Y, rc.Width - gap - ellipsingTringgering, rc.Height); TextUtil.DrawText(g, text, Font, drawRect); } m.Result = (IntPtr)CustomDrawReturnFlags.CDRF_SKIPDEFAULT; }
void DoListCustomDrawing(ref Message m) { NMLVCUSTOMDRAW lvcd = (NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW)); int row = lvcd.nmcd.dwItemSpec; int col = lvcd.iSubItem; // If we don't have any items we must be doing something wrong // because the list is only going to request custom drawing of items // in the list, if we have items in the list, the Items cannot possibly // be zero Debug.Assert(Items.Count != 0); ListViewItem lvi = Items[row]; Rectangle rc = GetSubItemRect(row, col); // Draw the item // We did not need to actually paint the items that are not selected // but doing all the painting ourselves eliminates some random bugs where // the list sometimes did not update a subitem that was not selected anymore // leaving the subitem with a different background color // than the rest of the row using (Graphics g = Graphics.FromHdc(lvcd.nmcd.hdc)) { // Draw Fill Rectangle if (IsRowSelected(row)) { int subItemOffset = 2; if (GridLines) { subItemOffset = 3; } g.FillRectangle(new SolidBrush(ColorUtil.VSNetSelectionColor), rc.Left + 1, rc.Top + 1, rc.Width - 2, rc.Height - subItemOffset); // Draw Border if (col == 0) { Color borderColor = SystemColors.Highlight; int heightOffset = 1; if (GridLines) { heightOffset = 2; } g.DrawRectangle(new Pen(borderColor), rc.Left + 1, rc.Top, rc.Width - 2, rc.Height - heightOffset); } } else { if (col == lastSortedColumn) { if (col == 0) { rc = AdjustFirstItemRect(rc); } g.FillRectangle(new SolidBrush(Color.FromArgb(247, 247, 247)), rc.Left, rc.Top, rc.Width, rc.Height); } else { if (col == 0) { rc = AdjustFirstItemRect(rc); } g.FillRectangle(new SolidBrush(SystemColors.Window), rc.Left, rc.Top, rc.Width, rc.Height); } } // Adjust rectangle, when getting the rectangle for column zero // the rectangle return is the one for the whole control if (col == 0) { rc = AdjustFirstItemRect(rc); } // Draw Text string text = GetSubItemText(row, col); Size textSize = TextUtil.GetTextSize(g, text, Font); int gap = 4; Point pos = new Point(rc.Left + gap, rc.Top + ((rc.Height - textSize.Height) / 2)); // I use the Windows API instead of the Graphics object to draw the string // because the Graphics object draws ellipes without living blank spaces in between // the DrawText API adds those blank spaces in between int ellipsingTringgering = 8; if (CheckBoxes && col == 0) { // draw checkbox int checkIndex = 0; if (lvi.Checked) { checkIndex = 1; } g.DrawImage(checkBoxesImageList.Images[checkIndex], rc.Left + gap, rc.Top); pos.X += IMAGE_WIDTH; rc.Width = rc.Width - IMAGE_WIDTH; } else if (col == 0 && CheckBoxes == false && lvi.ImageIndex != -1 && lvi.ImageList != null) { ImageList imageList = lvi.ImageList; Image image = imageList.Images[lvi.ImageIndex]; if (image != null) { g.DrawImage(imageList.Images[lvi.ImageIndex], rc.Left + gap, rc.Top); pos.X += IMAGE_WIDTH; rc.Width = rc.Width - IMAGE_WIDTH; } } Rectangle drawRect = new Rectangle(pos.X + 2, pos.Y, rc.Width - gap - ellipsingTringgering, rc.Height); TextUtil.DrawText(g, text, Font, drawRect); } // Put structure back in the message Marshal.StructureToPtr(lvcd, m.LParam, true); m.Result = (IntPtr)CustomDrawReturnFlags.CDRF_SKIPDEFAULT; }