Visual Basic 2005 - 如何建立一個主控描繪的TreeView控件

如果您要建立一個主控描繪的 TreeView 控件,也就是說,想要自行撰寫程序代碼來繪製 TreeView 控件的話,必須將 DrawMode 屬性設定成 TreeViewDrawMode.OwnerDrawAll TreeViewDrawMode.OwnerDrawText,並且替 DrawNode 事件處理例程撰寫程序代碼。

 

圖表 1 所示者是 TreeViewDrawMode 列舉類型的成員及其所代表的意義。

 

成員名稱

說明

Normal

此爲默認值,表示TreeView控件將由操作系統來繪製。 

OwnerDrawAll

此表示TreeView控件之節點的所有項目都將由您自行繪製,包括:圖示、複選框、加號、減號、以及連接節點的線條。 

OwnerDrawText

此表示TreeView控件之節點的卷標部分將由您自行繪製,至於節點的其它項目則由操作系統來繪製,包括:圖示、複選框、加號、減號、以及連接節點的線條。 

圖表1
                      圖表2
 
圖表 2 所示者是我們所撰寫之程序範例的執行畫面,此接口中的TreeView 控件擁有下列特色:

 

q          如果庫存量低於安全存量,便會在節點之卷標文字的右側額外顯示出一個標記文字“低於安全存量,請儘快補貨。”

q          用戶除了可以按一下卷標文字來選取節點之外,如果該節點額外顯示出標記文字的話,也可以按一下標記文字“低於安全存量,請儘快補貨。”來選取節點。

q          標記文字“低於安全存量,請儘快補貨。”採用加底線的粗斜體之標楷體字型,而且是×××的,這些都是我們通過程序代碼來自訂的。

q          被選取之節點的背景色是綠色,這也是我們通過程序代碼來自訂的。

 

顯而易見地,本程序示範的TreeView控件是一個主控描繪的TreeView控件,其設計技巧說明如下:

 

q          請如下所示,建立一個給節點之標記文字使用的Font對象:

Private tagFont As New Font("標楷體", 9, _
  FontStyle.Bold Or FontStyle.Italic Or FontStyle.Underline)

q          用戶自訂程序 LoadDataToTreeView() 負責將數據庫數據表中的數據填入TreeView控件中而成爲節點。我們以產品名稱作爲跟節點,並以其它字段的內容作爲子節點,而在加入子節點時,會判斷「庫存量」字段的內容是否低於「安全存量」字段的內容,如果如此的話,便將文字符串“低於安全庫存,請儘快補貨。”存入該節點的Tag屬性中:

While drProduct.Read()
  ' 以產品名稱作爲根節點。
  rootNode = New TreeNode(drProduct(0).ToString)
  TreeView1.Nodes.Add(rootNode)

  ' 以其它字段的內容作爲子節點。
  For i As Integer = 1 To nFieldCount – 1
     childNode = New TreeNode( _
       drProduct.GetName(i) & "" & drProduct(i).ToString)
     TreeView1.Nodes(nRow).Nodes.Add(childNode)
     ' 如果庫存量低於安全庫存,則將警示訊息儲
     ' 存於節點的Tag屬性中。
     If drProduct.GetSqlInt16(3) < drProduct.GetSqlInt16(4) Then
        TreeView1.Nodes(nRow).Nodes(0).Tag = _
            "低於安全庫存,請儘快補貨。"
     End If
  Next
  nRow += 1
End While

q          窗體之Load事件處理例程中的下面這一道陳述式,表示要求TreeView控件採用主控描繪:

TreeView1.DrawMode = TreeViewDrawMode.OwnerDrawText

q          TreeView控件的DrawNode事件處理例程撰寫程序代碼,以便進行節點的繪製作業:

Private Sub TreeView1_DrawNode(ByVal sender As Object, _
  ByVal e As DrawTreeNodeEventArgs) Handles TreeView1.DrawNode

  ' 繪製被選取之節點的背景色與節點文字。
  If (e.State And TreeNodeStates.Selected) <> 0 Then

     ' 繪製被選取之節點的背景色。如果該節點擁有標記文字
     ' 「低於安全庫存,請儘快補貨。」的話,NodeBounds方法
     ' 會使得醒目提示區域擁有足夠的大小來容納它。
     e.Graphics.FillRectangle(Brushes.Green, NodeBounds(e.Node))

     ' 提取節點字型。如果節點字型未被設定,
     ' 就使用TreeView的字型。
     Dim nodeFont As Font = e.Node.NodeFont
     If nodeFont Is Nothing Then
        nodeFont = CType(sender, TreeView).Font
     End If

     ' 繪製節點文字。
     e.Graphics.DrawString(e.Node.Text, nodeFont, _
       Brushes.White, e.Bounds.Left - 2, e.Bounds.Top)
  Else
     e.DrawDefault = True
  End If

  ' 如果存在節點標記,就將它繪製在節點標籤的右側。
  If (e.Node.Tag IsNot Nothing) Then
     e.Graphics.DrawString(e.Node.Tag.ToString(), tagFont, _
       Brushes.Yellow, e.Bounds.Right + 2, e.Bounds.Top)
  End If

  ' 如果節點擁有焦點,便將焦點矩形繪製得夠大
  ' 以便能夠容納節點卷標文字。
  If (e.State And TreeNodeStates.Focused) <> 0 Then
     Using focusPen As New Pen(Color.Black)
       focusPen.DashStyle = _
         System.Drawing.Drawing2D.DashStyle.Dot
       Dim focusBounds As Rectangle = NodeBounds(e.Node)
       focusBounds.Size = New Size(focusBounds.Width - 1, _
         focusBounds.Height - 1)
       e.Graphics.DrawRectangle(focusPen, focusBounds)
     End Using
  End If
End Sub

q          TreeView控件的MouseDown事件處理例程撰寫下列程序代碼,使得用戶可以按一下標記文字“低於安全庫存,請儘快補貨。”來選取節點:

' 不論用戶按一下節點卷標或節點標記都選取該節點。
Private Sub TreeView1_MouseDown(ByVal sender As Object, _
  ByVal e As MouseEventArgs) Handles TreeView1.MouseDown
  Dim clickedNode As TreeNode = TreeView1.GetNodeAt(e.X, e.Y)
  If NodeBounds(clickedNode).Contains(e.X, e.Y) Then
     TreeView1.SelectedNode = clickedNode
  End If
End Sub

q          用戶自訂函式NodeBounds能夠傳回所傳遞進來之節點的邊界範圍,包括節點卷標以及節點標記所佔用的區域:

Private Function NodeBounds(ByVal node As TreeNode) As Rectangle
  ' 將傳回值設定成正常的節點邊界範圍。
  Dim bounds As Rectangle = node.Bounds
  If (node.Tag IsNot Nothing) Then
     ' 取得TreeView控件的Graphics對象並使用
     ' 它來計算節點標記的顯示寬度。
     Dim g As Graphics = TreeView1.CreateGraphics()
     Dim tagWidth As Integer = CInt(g.MeasureString( _
         node.Tag.ToString(), tagFont).Width) + 6

     ' 使用計算所得的值來調整節點邊界範圍。
     bounds.Offset(tagWidth \ 2, 0)
     bounds = Rectangle.Inflate(bounds, tagWidth \ 2, 0)
  End If
  Return bounds
End Function

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章