Проблема с TreeView.DrawNode - OwnerDrawText - PullRequest
9 голосов
/ 13 января 2010

У меня есть приложение, которое подключено к удаленному серверу и опрашивает данные при необходимости. У этого есть 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);
    }
}

Я подумал, что этого будет достаточно, однако это вызывает некоторые проблемы;

  1. Когда узел выбран, сфокусирован или нет, он не охватывает весь текст, пример (надеюсь, imgur в порядке).
  2. Когда узел сфокусирован, пунктирный контур также не отображается. Если сравнить с этим примером . Узлы с «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);
   }
  }
 }

Однако, результаты были это . (Обратите внимание, используется розовый, чтобы различать цвета). Как вы можете видеть, выделенный фон не распространяется полностью на точку, на которой находится сфокусированная пунктирная линия. И есть еще одна коробка, которая также нарисована.

Я немного озадачен тем, как это исправить. Все, что я хочу, это иметь серый курсив, когда что-то загружено. Первый и самый простой подход не совсем работает, а во втором методе мне кажется, что я слишком много делаю.

После всего этого, есть ли у кого-нибудь предложения о том, как сделать это правильно, потому что должен быть более простой способ.

Заранее спасибо.

1 Ответ

14 голосов
/ 13 января 2010

Вам нужно будет использовать TextRenderer.DrawText (). Это то, что использует TreeView, он отображает текст немного отличается от Graphics.DrawString ().

...