/// <summary> /// Erases Item /// </summary> private void EraseItem(ref NMLVCUSTOMDRAW customDraw) { try { using (Graphics g = Graphics.FromHdc(customDraw.nmcd.hdc)) { Rectangle rect = new Rectangle(customDraw.nmcd.rc.left, customDraw.nmcd.rc.top, customDraw.nmcd.rc.right - customDraw.nmcd.rc.left, customDraw.nmcd.rc.bottom - customDraw.nmcd.rc.top); g.FillRectangle(new SolidBrush(BackColor), rect); } } catch (Exception ex) { System.Diagnostics.Trace.WriteLine("CustomListView.EraseItem failed : " + ex, "UI"); } }
/// <summary> /// Draws Item /// </summary> private void DrawItem(ref NMLVCUSTOMDRAW customDraw) { try { ListViewItem item = this.Items[customDraw.nmcd.dwItemSpec]; if (myItemPainter != null && myItemPainter.IsHandled(item)) { using (Graphics g = Graphics.FromHdc(customDraw.nmcd.hdc)) { myItemPainter.Draw(item, g, new Rectangle(0, 0, ClientSize.Width, 0)); } } } catch (Exception ex) { System.Diagnostics.Trace.WriteLine("CustomListView.DrawItem failed : " + ex, "UI"); } }
/// <summary> /// Handles the NM_CUSTOMDRAW notification /// </summary> private void OnCustomDraw(ref NMLVCUSTOMDRAW customDraw, ref Message m) { ListViewItem item; switch (customDraw.nmcd.dwDrawStage) { case Win32Declarations.CDDS_PREPAINT: m.Result = (IntPtr)(Win32Declarations.CDRF_NOTIFYITEMDRAW | Win32Declarations.CDRF_NOTIFYPOSTPAINT); break; case Win32Declarations.CDDS_ITEMPREPAINT: item = Items[customDraw.nmcd.dwItemSpec]; if (myItemPainter != null && item != null && myItemPainter.IsHandled(item)) { m.Result = (IntPtr)(Win32Declarations.CDRF_NOTIFYITEMDRAW | Win32Declarations.CDRF_NOTIFYPOSTPAINT); } else { m.Result = (IntPtr)Win32Declarations.CDRF_NOTIFYITEMDRAW; } break; case Win32Declarations.CDDS_ITEMPOSTPAINT: DrawItem(ref customDraw); break; case Win32Declarations.CDDS_POSTERASE: EraseItem(ref customDraw); break; default: m.Result = (IntPtr)Win32Declarations.CDRF_DODEFAULT; break; } }
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; }
private bool HandleCustomDraw(ref Message msg) { // TODO this needs to be cleaned if (QTUtility.CheckConfig(Settings.AlternateRowColors) && (ShellBrowser.ViewMode == FVM.DETAILS)) { NMLVCUSTOMDRAW structure = (NMLVCUSTOMDRAW)Marshal.PtrToStructure(msg.LParam, typeof(NMLVCUSTOMDRAW)); int dwItemSpec = 0; if ((ulong)structure.nmcd.dwItemSpec < Int32.MaxValue) { dwItemSpec = (int)structure.nmcd.dwItemSpec; } switch (structure.nmcd.dwDrawStage) { case CDDS.SUBITEM | CDDS.ITEMPREPAINT: iListViewItemState = (int)PInvoke.SendMessage( ListViewController.Handle, LVM.GETITEMSTATE, structure.nmcd.dwItemSpec, (IntPtr)(LVIS.FOCUSED | LVIS.SELECTED | LVIS.DROPHILITED)); if (!QTUtility.IsXP) { int num4 = lstColumnFMT[structure.iSubItem]; structure.clrTextBk = QTUtility.ShellViewRowCOLORREF_Background; structure.clrText = QTUtility.ShellViewRowCOLORREF_Text; Marshal.StructureToPtr(structure, msg.LParam, false); bool drawingHotItem = (dwItemSpec == GetHotItem()); bool fullRowSel = !QTUtility.CheckConfig(Settings.ToggleFullRowSelect); msg.Result = (IntPtr)(CDRF.NEWFONT); if (structure.iSubItem == 0 && !drawingHotItem) { if (iListViewItemState == 0 && (num4 & 0x600) != 0) { msg.Result = (IntPtr)(CDRF.NEWFONT | CDRF.NOTIFYPOSTPAINT); } else if (iListViewItemState == LVIS.FOCUSED && !fullRowSel) { msg.Result = (IntPtr)(CDRF.NEWFONT | CDRF.NOTIFYPOSTPAINT); } } if (structure.iSubItem > 0 && (!fullRowSel || !drawingHotItem)) { if (!fullRowSel || (iListViewItemState & (LVIS.SELECTED | LVIS.DROPHILITED)) == 0) { using (Graphics graphics = Graphics.FromHdc(structure.nmcd.hdc)) { if (QTUtility.sbAlternate == null) { QTUtility.sbAlternate = new SolidBrush(QTUtility2.MakeColor(QTUtility.ShellViewRowCOLORREF_Background)); } graphics.FillRectangle(QTUtility.sbAlternate, structure.nmcd.rc.ToRectangle()); } } } } else { msg.Result = (IntPtr)(CDRF.NOTIFYPOSTPAINT); } return(true); case CDDS.SUBITEM | CDDS.ITEMPOSTPAINT: { RECT rc = structure.nmcd.rc; if (QTUtility.IsXP) { rc = PInvoke.ListView_GetItemRect(ListViewController.Handle, dwItemSpec, structure.iSubItem, 2); } else { rc.left += 0x10; } bool flag3 = false; bool flag4 = false; bool flag5 = QTUtility.CheckConfig(Settings.DetailsGridLines); bool flag6 = QTUtility.CheckConfig(Settings.ToggleFullRowSelect) ^ !QTUtility.IsXP; bool flag7 = false; if (QTUtility.IsXP && QTUtility.fSingleClick) { flag7 = (dwItemSpec == GetHotItem()); } LVITEM lvitem = new LVITEM(); lvitem.pszText = Marshal.AllocHGlobal(520); lvitem.cchTextMax = 260; lvitem.iSubItem = structure.iSubItem; lvitem.iItem = dwItemSpec; lvitem.mask = 1; IntPtr ptr3 = Marshal.AllocHGlobal(Marshal.SizeOf(lvitem)); Marshal.StructureToPtr(lvitem, ptr3, false); PInvoke.SendMessage(ListViewController.Handle, LVM.GETITEM, IntPtr.Zero, ptr3); if (QTUtility.sbAlternate == null) { QTUtility.sbAlternate = new SolidBrush(QTUtility2.MakeColor(QTUtility.ShellViewRowCOLORREF_Background)); } using (Graphics graphics2 = Graphics.FromHdc(structure.nmcd.hdc)) { Rectangle rect = rc.ToRectangle(); if (flag5) { rect = new Rectangle(rc.left + 1, rc.top, rc.Width - 1, rc.Height - 1); } graphics2.FillRectangle(QTUtility.sbAlternate, rect); if (QTUtility.IsXP && ((structure.iSubItem == 0) || flag6)) { flag4 = (iListViewItemState & 8) == 8; if ((iListViewItemState != 0) && (((iListViewItemState == 1) && fListViewHasFocus) || (iListViewItemState != 1))) { int width; if (flag6) { width = rc.Width; } else { width = 8 + ((int)PInvoke.SendMessage(ListViewController.Handle, LVM.GETSTRINGWIDTH, IntPtr.Zero, lvitem.pszText)); if (width > rc.Width) { width = rc.Width; } } Rectangle rectangle2 = new Rectangle(rc.left, rc.top, width, flag5 ? (rc.Height - 1) : rc.Height); if (((iListViewItemState & 2) == 2) || flag4) { if (flag4) { graphics2.FillRectangle(SystemBrushes.Highlight, rectangle2); } else if (QTUtility.fSingleClick && flag7) { graphics2.FillRectangle(fListViewHasFocus ? SystemBrushes.HotTrack : SystemBrushes.Control, rectangle2); } else { graphics2.FillRectangle(fListViewHasFocus ? SystemBrushes.Highlight : SystemBrushes.Control, rectangle2); } flag3 = true; } if ((fListViewHasFocus && ((iListViewItemState & 1) == 1)) && !flag6) { ControlPaint.DrawFocusRectangle(graphics2, rectangle2); } } } if (!QTUtility.IsXP && ((iListViewItemState & 1) == 1)) { int num6 = rc.Width; if (!flag6) { num6 = 4 + ((int)PInvoke.SendMessage(ListViewController.Handle, LVM.GETSTRINGWIDTH, IntPtr.Zero, lvitem.pszText)); if (num6 > rc.Width) { num6 = rc.Width; } } Rectangle rectangle = new Rectangle(rc.left + 1, rc.top + 1, num6, flag5 ? (rc.Height - 2) : (rc.Height - 1)); ControlPaint.DrawFocusRectangle(graphics2, rectangle); } } IntPtr zero = IntPtr.Zero; IntPtr hgdiobj = IntPtr.Zero; if (QTUtility.IsXP && QTUtility.fSingleClick) { LOGFONT logfont; zero = PInvoke.GetCurrentObject(structure.nmcd.hdc, 6); PInvoke.GetObject(zero, Marshal.SizeOf(typeof(LOGFONT)), out logfont); if ((structure.iSubItem == 0) || flag6) { logfont.lfUnderline = ((QTUtility.iIconUnderLineVal == 3) || flag7) ? ((byte)1) : ((byte)0); } else { logfont.lfUnderline = 0; } hgdiobj = PInvoke.CreateFontIndirect(ref logfont); PInvoke.SelectObject(structure.nmcd.hdc, hgdiobj); } PInvoke.SetBkMode(structure.nmcd.hdc, 1); int dwDTFormat = 0x8824; if (QTUtility.IsRTL ? ((lstColumnFMT[structure.iSubItem] & 1) == 0) : ((lstColumnFMT[structure.iSubItem] & 1) == 1)) { if (QTUtility.IsRTL) { dwDTFormat &= -3; } else { dwDTFormat |= 2; } rc.right -= 6; } else if (structure.iSubItem == 0) { rc.left += 2; rc.right -= 2; } else { rc.left += 6; } if (flag3) { PInvoke.SetTextColor(structure.nmcd.hdc, QTUtility2.MakeCOLORREF((fListViewHasFocus || flag4) ? SystemColors.HighlightText : SystemColors.WindowText)); } else { PInvoke.SetTextColor(structure.nmcd.hdc, QTUtility.ShellViewRowCOLORREF_Text); } PInvoke.DrawTextExW(structure.nmcd.hdc, lvitem.pszText, -1, ref rc, dwDTFormat, IntPtr.Zero); Marshal.FreeHGlobal(lvitem.pszText); Marshal.FreeHGlobal(ptr3); msg.Result = IntPtr.Zero; if (zero != IntPtr.Zero) { PInvoke.SelectObject(structure.nmcd.hdc, zero); } if (hgdiobj != IntPtr.Zero) { PInvoke.DeleteObject(hgdiobj); } return(true); } case CDDS.ITEMPREPAINT: if ((dwItemSpec % 2) == 0) { msg.Result = (IntPtr)0x20; return(true); } msg.Result = IntPtr.Zero; return(false); case CDDS.PREPAINT: { HDITEM hditem = new HDITEM(); hditem.mask = 4; IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(hditem)); Marshal.StructureToPtr(hditem, ptr, false); IntPtr hWnd = PInvoke.SendMessage(ListViewController.Handle, LVM.GETHEADER, IntPtr.Zero, IntPtr.Zero); int num2 = (int)PInvoke.SendMessage(hWnd, 0x1200, IntPtr.Zero, IntPtr.Zero); if (lstColumnFMT == null) { lstColumnFMT = new List <int>(); } else { lstColumnFMT.Clear(); } for (int i = 0; i < num2; i++) { PInvoke.SendMessage(hWnd, 0x120b, (IntPtr)i, ptr); hditem = (HDITEM)Marshal.PtrToStructure(ptr, typeof(HDITEM)); lstColumnFMT.Add(hditem.fmt); } Marshal.FreeHGlobal(ptr); fListViewHasFocus = ListViewController.Handle == PInvoke.GetFocus(); msg.Result = (IntPtr)0x20; return(true); } } } return(false); }
CustomDrawReturnFlags OnCustomDraw(NMLVCUSTOMDRAW lvcd) { DrawstageFlags df = (DrawstageFlags)lvcd.nmcd.dwDrawStage; if (df == DrawstageFlags.CDDS_PREPAINT) { return(CustomDrawReturnFlags.CDRF_NOTIFYITEMDRAW); } if (df == DrawstageFlags.CDDS_ITEMPREPAINT) { return(CustomDrawReturnFlags.CDRF_NOTIFYSUBITEMDRAW); } if (df == (DrawstageFlags.CDDS_SUBITEM | DrawstageFlags.CDDS_ITEMPREPAINT)) { return(CustomDrawReturnFlags.CDRF_NOTIFYPOSTPAINT); } if (df == (DrawstageFlags.CDDS_SUBITEM | DrawstageFlags.CDDS_ITEMPOSTPAINT)) { if (lvcd.iSubItem == 3) // Done { ListViewItem lvi = Items[lvcd.nmcd.dwItemSpec]; if (lvi.SubItems[3].Text != "" && lvi.ListView.Columns[3].Width != 0) { float value = float.Parse(lvi.SubItems[3].Text.Split(' ')[0]); Rectangle bounds = lvi.SubItems[3].Bounds; if (value < 0) { value = 0; } else if (value > 100) { value = 100; } bounds.Inflate(-2, -2); using (Graphics g = Graphics.FromHdc(lvcd.nmcd.hdc)) { RectangleF rcItem = new RectangleF(bounds.X + 1, bounds.Y + 1, bounds.Width - 2, bounds.Height - 2); RectangleF rcLeft = new RectangleF(bounds.X + 1, bounds.Y + 1, (bounds.Width - 2) * value / 100, bounds.Height - 2); RectangleF rcRight = new RectangleF(bounds.X + 1 + (bounds.Width - 2) * value / 100, bounds.Y + 1, bounds.Width - 2 - ((bounds.Width - 2) * value / 100), bounds.Height - 2); StringFormat sf = new StringFormat(); g.FillRectangle(new SolidBrush(Color.FromKnownColor(KnownColor.Highlight)), rcLeft); g.FillRectangle(new SolidBrush(Color.FromKnownColor(KnownColor.Window)), rcRight); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; sf.FormatFlags = StringFormatFlags.NoWrap; g.SetClip(rcLeft); g.DrawString(string.Format("{0:F} %", value), Util.GetInterfaceFont(), new SolidBrush(Color.FromKnownColor(KnownColor.HighlightText)), rcItem, sf); g.SetClip(rcRight); g.DrawString(string.Format("{0:F} %", value), Util.GetInterfaceFont(), new SolidBrush(Color.FromKnownColor(KnownColor.WindowText)), rcItem, sf); g.SetClip(bounds); g.DrawRectangle(new Pen(Color.FromKnownColor(KnownColor.Control)), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); } } } return(CustomDrawReturnFlags.CDRF_DODEFAULT); } return(CustomDrawReturnFlags.CDRF_DODEFAULT); }