2009-06-16 17 views
8

我將DrawMode設置爲OwnerDrawText並添加到DrawNode事件,添加我的代碼以我想要的方式繪製文本,並且所有工作都很好保存對於選擇節點時某些奇怪的黑色選擇突出顯示。C#:TreeView所有者繪圖與ownerdrawtext和奇怪的黑色突出顯示單擊節點時

沒問題,我添加了邏輯來檢查節點的狀態是否突出顯示,並繪製了我自己的突出顯示,除了在單擊節點時添加了黑色突出顯示,而不僅僅是選中了......突出顯示被我的矩形一旦鼠標按鈕被釋放,但確實被繪製並眨眼......這很煩人。 :/

顯然我忘了實際上問我的問題......如果沒有完全處理圖紙,如何擺脫選擇?

回答

12

以我的經驗,你通常不能。要麼你自己畫這個東西,要麼你沒有。如果你試圖將你的圖形複製到控件所繪製的圖形上,那麼最終會出現毛刺。

這有點痛苦,因爲你必須處理焦點矩形,選擇高光,並自己繪製所有的字形。

從好的一面來看,Visual Styles可以用來做大部分的工作。

這裏有一些代碼可以讓你瞭解大多數情況(這是不完整的,因爲它使用了一些未包括的方法,並且它不能完全呈現正常樹視圖的功能,因爲它支持畢業生填充的項目和列,但應該是一個方便的參考)

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); 
     } 
    } 
相關問題