TreeView.DrawNode的问题 - OwnerDrawText

Emm*_*l F 9 c# treeview ownerdrawn winforms

我有一个连接到远程服务器的应用程序,并在需要时轮询数据.它有一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为这就够了,但是,这已经引起了一些问题;

  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);
   }
  }
 }
Run Code Online (Sandbox Code Playgroud)

然而,结果是这样的.(注意,使用粉红色来区分颜色).如您所见,突出显示的背景并未一直延伸到聚焦虚线所在的位置.而且还有另一个盒子也被绘制出来.

我有点难以理解如何解决这个问题.我想要的是在加载某些东西时使用灰色斜体文本.第一种也是最简单的方法并不常用,而第二种方法感觉就像我做得太多了.

毕竟,有没有人对如何正确地做这个有任何建议,因为必须有一个更简单的方法.

先感谢您.

Han*_*ant 14

您需要使用TextRenderer.DrawText().这就是TreeView使用的,它呈现的文本与Graphics.DrawString()略有不同.

  • 这仍然无法纠正所有图形故障.即使我的DrawNode处理程序只是将DrawDefault设置为true并立即返回,它仍然会在取消选择节点后仍然保留选择矩形背景的残余.此外,当使用DrawMode = OwnerDrawText时,文本偏离中心(垂直),即使DrawDefault是所有使用的.需要向下移动一个像素以匹配DrawMode = Normal时渲染的像素.问题是控件的绘图方法是windows原生绘图代码和框架绘图代码的混合,它们非常不一致. (3认同)