C#:TreeView 所有者绘制带有 ownerdrawtext 和单击节点时奇怪的黑色突出显示
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1003459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#: TreeView owner drawing with ownerdrawtext and the weird black highlighting when clicking on a node
提问by Austin Hanson
I set the DrawMode to OwnerDrawText and tacked on to the DrawNode event, added my code to draw the text the way I want and all works well save for some odd black selection highlighting when a node is selected.
我将 DrawMode 设置为 OwnerDrawText 并附加到 DrawNode 事件,添加了我的代码以按照我想要的方式绘制文本,并且除了在选择节点时突出显示一些奇怪的黑色选择之外,一切都运行良好。
No problem, I added logic to check for if the node's state was highlighted and drew my own highlighting except the black highlighting gets added when a node is clicked, not just selected... The highlight gets drawn over by my rectangle once the mouse button is released but does get drawn and blinks...it's annoying. :/
没问题,我添加了逻辑来检查节点的状态是否被突出显示并绘制了我自己的突出显示,除了在单击节点时添加黑色突出显示,而不仅仅是选择......一旦鼠标按钮,突出显示就会被我的矩形绘制被释放但确实被绘制并闪烁......这很烦人。:/
Apparently I forgot to actually ask my question...How would one go about getting rid of the selection without completely handling the drawing?
显然我忘了问我的问题......如何在不完全处理绘图的情况下摆脱选择?
采纳答案by Jason Williams
In my experience you usually can't. Either you draw the item yourself or you don't. If you try to composite your graphics on top of those drawn by the control, you'll end up with glitches.
根据我的经验,你通常不能。要么您自己绘制该项目,要么不绘制。如果您尝试在控件绘制的图形之上合成图形,最终会出现故障。
It is a bit of a pain because you have to handle focus rectangles, selection highlights, and drawing all the glyphs yourself.
这有点痛苦,因为您必须自己处理焦点矩形、选择高光和绘制所有字形。
On the plus side, Visual Stylescan be used to do most of the work.
从好的方面来说,视觉样式可用于完成大部分工作。
Here's some code that will get you most of the way there (it's incomplete, in that it uses some methods not included, and it doesn't render exactly what a normal treeview does because it supports grad filled items and columns, but should be a handy reference)
这里有一些代码可以让您完成大部分工作(它不完整,因为它使用了一些未包含的方法,并且它不能完全呈现普通树视图所做的事情,因为它支持 grad 填充的项目和列,但应该是一个方便参考)
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);
}
}