У меня есть приложение, которое подключено к удаленному серверу и опрашивает данные при необходимости. У этого есть TreeView, где Узлы представляют доступные объекты, и цвет текста указывает, были ли загружены данные или нет; Выделенный курсивом означает, что не загружен, черный, обычный текст загружен.
В настоящее время я установил TreeView на OwnderDrawText, и функция TreeView.DrawNode просто рисует текст следующим образом:
private void TreeViewDrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (!e.Node.IsVisible)
{
return;
}
bool bLoaded = false;
if (e.Bounds.Location.X >= 0 && e.Bounds.Location.Y >= 0)
{
if(e.Node.Tag != null)
{
//...
// code determining whether data has been loaded is done here
// setting bLoaded true or false
//...
}
else
{
e.DrawDefault = true;
return;
}
Font useFont = null;
Brush useBrush = null;
if (bLoaded)
{
useFont = e.Node.TreeView.Font;
useBrush = SystemBrushes.WindowText;
}
else
{
useFont = m_grayItallicFont;
useBrush = SystemBrushes.GrayText;
}
e.Graphics.DrawString(e.Node.Text, useFont, useBrush, e.Bounds.Location);
}
}
Я подумал, что этого будет достаточно, однако это вызывает некоторые проблемы;
- Когда узел выбран, сфокусирован или нет, он не охватывает весь текст, пример (надеюсь, imgur в порядке).
- Когда узел сфокусирован, пунктирный контур также не отображается. Если сравнить с этим примером . Узлы с «log» в тексте используют e.DefaultDraw = true
Я пытался следовать примеру, приведенному в этом вопросе. Выглядело это примерно так:
private void TreeViewDrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (!e.Node.IsVisible)
{
return;
}
bool bLoaded = false;
if (e.Bounds.Location.X >= 0 && e.Bounds.Location.Y >= 0)
{
if(e.Node.Tag != null)
{
//...
// code determining whether data has been loaded is done here
// setting bLoaded true or false
//...
}
else
{
e.DrawDefault = true;
return;
}
//Select the font and brush depending on whether the property has been loaded
Font useFont = null;
Brush useBrush = null;
if (bLoaded)
{
useFont = e.Node.TreeView.Font;
useBrush = SystemBrushes.WindowText;
}
else
{
//member variable defined elsewhere
useFont = m_grayItallicFont;
useBrush = SystemBrushes.GrayText;
}
//Begin drawing of the text
//Get the rectangle that will be used to draw
Rectangle itemRect = e.Bounds;
//Move the rectangle over by 1 so it isn't on top of the check box
itemRect.X += 1;
//Figure out the text position
Point textStartPos = new Point(itemRect.Left, itemRect.Top);
Point textPos = new Point(textStartPos.X, textStartPos.Y);
//generate the text rectangle
Rectangle textRect = new Rectangle(textPos.X, textPos.Y, itemRect.Right - textPos.X, itemRect.Bottom - textPos.Y);
int textHeight = (int)e.Graphics.MeasureString(e.Node.Text, useFont).Height;
int textWidth = (int)e.Graphics.MeasureString(e.Node.Text, useFont).Width;
textRect.Height = textHeight;
//Draw the highlighted box
if ((e.State & TreeNodeStates.Selected) != 0)
{
//e.Graphics.FillRectangle(SystemBrushes.Highlight, textRect);
//use pink to see the difference
e.Graphics.FillRectangle(Brushes.Pink, textRect);
}
//widen the rectangle by 3 pixels, otherwise all of the text won't fit
textRect.Width = textWidth + 3;
//actually draw the text
e.Graphics.DrawString(e.Node.Text, useFont, useBrush, e.Bounds.Location);
//Draw the box around the focused node
if ((e.State & TreeNodeStates.Focused) != 0)
{
textRect.Width = textWidth;
Pen focusPen = new Pen(Color.Black);
focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
e.Graphics.DrawRectangle(focusPen, textRect);
}
}
}
Однако, результаты были это . (Обратите внимание, используется розовый, чтобы различать цвета). Как вы можете видеть, выделенный фон не распространяется полностью на точку, на которой находится сфокусированная пунктирная линия. И есть еще одна коробка, которая также нарисована.
Я немного озадачен тем, как это исправить. Все, что я хочу, это иметь серый курсив, когда что-то загружено. Первый и самый простой подход не совсем работает, а во втором методе мне кажется, что я слишком много делаю.
После всего этого, есть ли у кого-нибудь предложения о том, как сделать это правильно, потому что должен быть более простой способ.
Заранее спасибо.