科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VB6.0设计真正实用的TreeView控件

VB6.0设计真正实用的TreeView控件

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

默认的TreeView不能对节点进行操作,那么本文将告诉你如何...

作者:东方欲晓 来源:yesky 2007年10月15日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
二、设计事件的句柄

  在TVEdit工程中,TreeView控件的KeyDown事件句柄处理所有涉及键击的编辑操作,它用一个Select Case块判断用户按下的键,每一个Case语句对应一个键击事件。

  当用户按下Space键,我们调用StartLabelEdit方法将节点转入编辑模式。如果被按下的是Delete键,则调用TreeView.Nodes集合的Remove方法删除当前选中的节点。对于Insert键,则用下面的代码在当前选中的节点下添加一个新节点,使新节点处于编辑模式:

Set currNode = SmartTreeView.Nodes.Add (SmartTreeView.SelectedItem, tvwChild)
currNode.Text = ""
SmartTreeView.StartLabelEdit

  如果用户按下了Ctrl+Insert键,通过下面的代码添加一个新的根节点并让它处于编辑状态:

If Shift And vbCtrlMask Then
 Set currNode = SmartTreeView.Nodes.Add()
 currNode.Selected = True
 SmartTreeView.StartLabelEdit
End If

  每一个节点必须有一个键——字符串形式的标识符。对于新添加的或编辑过的节点,我们在编辑操作结束时生成一个1到10000000之间的随机数字,加上前缀“K”,以此作为节点的键。由于Rnd()函数不保证随机数字的唯一性,所以我们使用了一个循环,如果第一次生成的键已经被使用,VB会触发一个错误,这时我们继续循环,寻找另外的键。

Dim Repeat As Boolean
Repeat = True
While Repeat
 On Error Resume Next
 SmartTreeView.SelectedItem.Key = "K" & 1 + Int(Rnd() * 10000000)
 If Err.Number = 0 Then Repeat = False
Wend

  三、拖放操作

  TreeView控件本身不支持内部节点的拖放操作,所以我们要实现OLE拖放事件的句柄。首先必须把控件的OLEDragMode属性设置成ccOLEDragAutomatic,把OLEDropMode属性设置成ccOLEDropManual。当用户开始拖动一个节点,控件触发OLEStartDrag事件:

Private Sub SmartTreeView_OLEStartDrag( _
Data As MSComctlLib.DataObject, _
AllowedEffects As Long)
 Data.Clear
 If Not Me.SmartTreeView.SelectedItem Is Nothing Then
  Data.SetData Me.SmartTreeView.SelectedItem.Key,vbCFText
 End If
End Sub

  OLEStartDrag事件句柄把Data参数设置成被拖放节点的Key属性,稍后我们可以看到这个值的用处。当用户用鼠标拖着节点移动,VB触发OLEDragOver事件,下面给出了事件句柄的代码。当用户拖着节点经过其他节点时,其他节点不会自动以高亮度颜色显示,所以我们必须将TreeView控件的DropHighlight属性设置到适当的节点,以表明鼠标当前正处在该节点的位置上。鼠标所在位置的节点可通过控件的HitTest方法获知,HitTest方法的参数是指针的坐标。

Private Sub SmartTreeView_OLEDragOver _
(Data As MSComctlLib.DataObject, Effect As Long, _
Button As Integer, Shift As Integer, x As Single, _
y As Single, State As Integer)

 With SmartTreeView
  If State = vbLeave Then
   Set .DropHighlight = Nothing
  Else
   .DropHighlight = .HitTest(x, y)
  End If
 End With
 mfX = x
 mfY = y
 If y > 0 And y < 100 Then
  m_iScrollDir = -1
  Timer1.Enabled = True
 ElseIf y > (SmartTreeView.Height - 200) And _
  y < SmartTreeView.Height Then
  m_iScrollDir = 1
  Timer1.Enabled = True
 Else
  Timer1.Enabled = False
 End If
End Sub

  拖着节点经过其他可见的节点不存在什么问题,但要把节点拖到某个当前不在控件可见区域的节点就要复杂一些。为了实现这个功能,当鼠标拖着节点到达TreeView控件的顶部或底部时,我们必须强制TreeView滚动其可见区域。TVEdit工程利用了一个每200ms触发的Timer,以便分析当前鼠标指针所处的位置。如果鼠标拖着节点到达距离TreeView控件顶部或底部100 pixel的位置,控件显示的内容就必须滚动。有关这一技术的详细说明,有兴趣的读者可参见MSDN文章Q177743。

  SmartTreeView_OLEDragOver事件句柄有几行代码用来判断是否要滚动控件以及开启Timer,但实际的滚动操作由Timer的事件句柄完成。

  当用户拖着节点到达目的地后放开鼠标键,控件触发OLEDragDrop事件,这个事件句柄要提取出被拖动的节点,并把它放在当前高亮度显示的节点之下。前面我们把被拖动节点的Key放入了事件句柄的参数Data对象,现在可以利用这个Key方便地从Notes集合得到被拖动的节点,只要把这个节点的ParentNode属性设置成当前高亮度显示的节点,就完成了移动节点(及其所有子节点)的操作。注意被拖动的节点不能放入它自己的子节点之下,因为这会形成父子节点相互引用的循环引用关系。

Private Sub SmartTreeView_OLEDragDrop( _
Data As MSComctlLib.DataObject, Effect As Long, _
Button As Integer, Shift As Integer, x As Single, _
y As Single)

 Dim strKey As String
 Dim thisNode, DragNode As Node

 Set oNode = Me.SmartTreeView.HitTest(x, y)

 If Data.GetFormat(vbCFText) Then
  strKey = Data.GetData(vbCFText)
  Set oDragNode = SmartTreeView.Nodes(strKey)
  On Error Resume Next
  Set oDragNode.Parent = oNode
  If Err.Number = 35614 Then
   MsgBox "节点不能移动到此位置:不能创建循环引用关系。"
   On Error GoTo 0
  End If
  Set SmartTreeView.DropHighlight = Nothing
 End If
End Sub
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章