C#:TreeView所有者使用ownerdrawtext进行绘制,并在单击节点时使用奇怪的黑色突出显示

我将DrawMode设置为OwnerDrawText并添加到DrawNode事件,添加我的代码以我想要的方式绘制文本,并且一切正常,除了选择节点时突出显示的一些奇怪的黑色选项。

没问题,我添加了逻辑来检查节点的状态是否突出显示并绘制了我自己的突出显示,除了在单击节点时添加黑色突出显示,而不仅仅是选中…一旦鼠标按钮突出显示我的矩形突出显示被释放但确实被吸引并眨眼……这很烦人。 :/

显然我忘了真的问我的问题……如果不完全处理绘图,怎么会去除选择?

根据我的经验,你通常不能。 要么自己画画,要么不画画。 如果您尝试将图形合成到控件绘制的图形之上,则最终会出现毛刺。

这有点痛苦,因为您必须自己处理焦点矩形,选择高光以及绘制所有字形。

从好的方面来说, Visual Styles可以用来完成大部分工作。

这里有一些代码可以帮助你完成大部分工作(它不完整,因为它使用了一些未包含的方法,并且它不能正确呈现普通树视图的function,因为它支持渐变填充的项目和列,但应该是方便参考)

protected virtual void OnDrawTreeNode(object sender, DrawTreeNodeEventArgs e) { string text = e.Node.Text; Rectangle itemRect = e.Bounds; if (e.Bounds.Height < 1 || e.Bounds.Width < 1) return; int cIndentBy = 19; // TODO - support Indent value int cMargin = 6; // TODO - this is a bit random, it's slaved off the Indent in some way int cTwoMargins = cMargin * 2; int indent = (e.Node.Level * cIndentBy) + cMargin; int iconLeft = indent; // Where to draw parentage lines & icon/checkbox int textLeft = iconLeft + 16; // Where to draw text Color leftColour = e.Node.BackColor; Color textColour = e.Node.ForeColor; if (Bitfield.IsBitSet(e.State, TreeNodeStates.Grayed)) textColour = Color.FromArgb(255,128,128,128); // Grad-fill the background Brush backBrush = new SolidBrush(leftColour); e.Graphics.FillRectangle(backBrush, itemRect); // Faint underline along the bottom of each item Color separatorColor = ColourUtils.Mix(leftColour, Color.FromArgb(255,0,0,0), 0.02); Pen separatorPen = new Pen(separatorColor); e.Graphics.DrawLine(separatorPen, itemRect.Left, itemRect.Bottom-1, itemRect.Right, itemRect.Bottom-1); // Bodged to use Button styles as Treeview styles not available on my laptop... if (!HideSelection) { if (Bitfield.IsBitSet(e.State, TreeNodeStates.Selected) || Bitfield.IsBitSet(e.State, TreeNodeStates.Hot)) { Rectangle selRect = new Rectangle(textLeft, itemRect.Top, itemRect.Right - textLeft, itemRect.Height); VisualStyleRenderer renderer = new VisualStyleRenderer((ContainsFocus) ? VisualStyleElement.Button.PushButton.Hot : VisualStyleElement.Button.PushButton.Normal); renderer.DrawBackground(e.Graphics, selRect); // Bodge to make VisualStyle look like Explorer selections - overdraw with alpha'd white rectangle to fade the colour a lot Brush bodge = new SolidBrush(Color.FromArgb((Bitfield.IsBitSet(e.State, TreeNodeStates.Hot)) ? 224 : 128,255,255,255)); e.Graphics.FillRectangle(bodge, selRect); } } Pen dotPen = new Pen(Color.FromArgb(128,128,128)); dotPen.DashStyle = DashStyle.Dot; int midY = (itemRect.Top + itemRect.Bottom) / 2; // Draw parentage lines if (ShowLines) { int x = cMargin * 2; if (e.Node.Level == 0 && e.Node.PrevNode == null) { // The very first node in the tree has a half-height line e.Graphics.DrawLine(dotPen, x, midY, x, itemRect.Bottom); } else { TreeNode testNode = e.Node; // Used to only draw lines to nodes with Next Siblings, as in normal TreeViews for (int iLine = e.Node.Level; iLine >= 0; iLine--) { if (testNode.NextNode != null) { x = (iLine * cIndentBy) + (cMargin * 2); e.Graphics.DrawLine(dotPen, x, itemRect.Top, x, itemRect.Bottom); } testNode = testNode.Parent; } x = (e.Node.Level * cIndentBy) + cTwoMargins; e.Graphics.DrawLine(dotPen, x, itemRect.Top, x, midY); } e.Graphics.DrawLine(dotPen, iconLeft + cMargin, midY, iconLeft + cMargin + 10, midY); } // Draw Expand (plus/minus) icon if required if (ShowPlusMinus && e.Node.Nodes.Count > 0) { // Use the VisualStyles renderer to use the proper OS-defined glyphs Rectangle expandRect = new Rectangle(iconLeft-1, midY - 7, 16, 16); VisualStyleElement element = (e.Node.IsExpanded) ? VisualStyleElement.TreeView.Glyph.Opened : VisualStyleElement.TreeView.Glyph.Closed; VisualStyleRenderer renderer = new VisualStyleRenderer(element); renderer.DrawBackground(e.Graphics, expandRect); } // Draw the text, which is separated into columns by | characters Point textStartPos = new Point(itemRect.Left + textLeft, itemRect.Top); Point textPos = new Point(textStartPos.X, textStartPos.Y); Font textFont = e.Node.NodeFont; // Get the font for the item, or failing that, for this control if (textFont == null) textFont = Font; StringFormat drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Near; drawFormat.LineAlignment = StringAlignment.Center; drawFormat.FormatFlags = StringFormatFlags.NoWrap; string [] columnTextList = text.Split('|'); for (int iCol = 0; iCol < columnTextList.GetLength(0); iCol++) { Rectangle textRect = new Rectangle(textPos.X, textPos.Y, itemRect.Right - textPos.X, itemRect.Bottom - textPos.Y); if (mColumnImageList != null && mColumnImageList[iCol] != null) { // This column has an imagelist assigned, so we use the column text as an integer zero-based index // into the imagelist to indicate the icon to display int iImage = 0; try { iImage = MathUtils.Clamp(Convert.ToInt32(columnTextList[iCol]), 0, mColumnImageList[iCol].Images.Count); } catch(Exception) { iImage = 0; } e.Graphics.DrawImageUnscaled(mColumnImageList[iCol].Images[iImage], textRect.Left, textRect.Top); } else e.Graphics.DrawString(columnTextList[iCol], textFont, new SolidBrush(textColour), textRect, drawFormat); textPos.X += mColumnWidthList[iCol]; } // Draw Focussing box around the text if (e.State == TreeNodeStates.Focused) { SizeF size = e.Graphics.MeasureString(text, textFont); size.Width = (ClientRectangle.Width - 2) - textStartPos.X; size.Height += 1; Rectangle rect = new Rectangle(textStartPos, size.ToSize()); e.Graphics.DrawRectangle(dotPen, rect); // ControlPaint.DrawFocusRectangle(e.Graphics, Rect); } }