设置检查节点检查事件
Posted
技术标签:
【中文标题】设置检查节点检查事件【英文标题】:Setting Checked On NodeCheck Event 【发布时间】:2014-04-29 13:23:52 【问题描述】:在NodeCheck
事件期间设置选中的属性会导致它恢复到之前的状态。
例如:节点被检查,下面的事件被触发。它发现节点被检查并将其设置为假。如果我用中断遍历代码,节点将在用户界面中反映这一点。虽然,只要代码到达 end sub,复选框就会跳回设置为 true。
Private Sub treeviewExample_NodeCheck(ByVal Node As Object)
If Node.Checked = True Then
Node.Checked = False
ElseIf Node.Checked = False Then
Node.Checked = True
End If
end sub
如何在NodeCheck
事件期间设置checked 属性?
我已经尝试了解决方案here,它将节点设置为本地或全局变量,然后设置它,它做同样的事情。
【问题讨论】:
NodeCheck 事件被触发,因为节点的 Checked 值已更改。 Windows 为您检查/清除检查。您不必更改代码中的值,除非您想更改选中的值以响应用户执行其他操作。 我使用节点的方式是验证权限与否。如果用户没有安全性来编辑权限,那么我希望节点重置为其原始正确值,而不是向用户显示他/她有安全性来更改它。 请阅读:Should questions include “tags” in their titles? 【参考方案1】:您可以将 Checkboxes 属性设置为 False,并使用 Windows API 来设置 checkboxes 属性。然后使用 NodeClick 事件来选择是否选中或取消选中节点。
Option Explicit
Private Const TVS_CHECKBOXES As Long = &H100
Private Const GWL_STYLE As Long = (-16)
Private Const TVS_HASLINES As Long = 2
Private Const TV_FIRST As Long = &H1100
Private Const TVM_SETBKCOLOR As Long = (TV_FIRST + 29)
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Sub Form_Load()
SetTVCheckboxStyle TreeView1
End Sub
Private Sub SetTVCheckboxStyle(pobjTV As TreeView)
Dim lngCurStyle As Long
Dim lngResult As Long
' === Set the Checkbox style of the TreeView ===
' As advised by Microsoft, due to a bug in the TreeView control,
' set the Checkbox style of the TreeView by using the following
' API calls, rather than simply setting the "Checkboxes" property
' to True ...
lngCurStyle = GetWindowLong(pobjTV.hwnd, GWL_STYLE)
lngResult = SetWindowLong(pobjTV.hwnd, GWL_STYLE, _
lngCurStyle Or TVS_CHECKBOXES)
End Sub
当您添加节点时,请设置您希望禁用的节点的一些属性,以便稍后检查该属性。我选择使用 ForeColor 属性,因此禁用的节点将具有禁用的外观。然后使用 NodeClick 事件来检查、清除或忽略用户点击。
Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node)
If Node.ForeColor <> vbGrayText Then
Node.Checked = Not Node.Checked
End If
End Sub
【讨论】:
如果此解决方案对我有用,我仍在努力,但您可能需要查看GetWindowLongptr
和 SetWindowLongptr
函数,而不是 GetWindowLong
和 SetWindowLong
。它们似乎已被弃用,较新的功能同时支持 32 位和 64 位 Windows。 msdn.microsoft.com/en-us/library/windows/desktop/…
我还有一个问题是该事件也会在标签上触发。我怎么能覆盖标签点击VS。复选框点击?
我不确定您如何或是否可以从复选框点击中辨别标签。不幸的是,因为您不能禁用选定的节点,所以这只是一个杂项。另一种解决方案是根本不使用复选框,而是使用在各种状态下看起来像复选框的图像。 IMO 理想的解决方案是重新考虑 UI 设计。
令人失望的是,我无法在 Treeview 上采取行动,尽管我确实喜欢您的 imagelist 建议。谢谢【参考方案2】:
我遇到了这个问题,并找到了解决方法。
您不能在其自己的 NodeCheck 事件中设置树视图复选框的“已选中”。
但是,假设您正在捕获用户单击复选框,Treeview_Click 事件随后会立即触发(因为他们必须单击才能更改它),并且您可以在该事件中设置复选框。
因此,您需要做的就是存储对需要更改的复选框的引用,并在 Click 事件中设置它,然后再清除引用。
Private WithEvents tv As TreeView
Private checkBoxToSet_Node As Node
Private checkBoxToSet_value As Boolean
Private Sub tv_NodeCheck(ByVal Node As MSComctlLib.Node)
Dim prompt As VbMsgBoxResult
prompt = MsgBox("Do you REALLY want to set this checkbox?", vbQuestion + vbYesNoCancel)
' can't set the checked-ness here, so we store it
If (prompt <> vbYes) Then
Set checkBoxToSet_Node = Node
checkBoxToSet_value = Not Node.checked
End If
End Sub
Private Sub tv_Click()
' check if we had previously set a node to have its checkbox changed
If (Not checkBoxToSet_Node Is Nothing) Then
tv.Nodes(checkBoxToSet_Node.key).checked = checkBoxToSet_value
Set checkBoxToSet_Node = Nothing
End If
End Sub
【讨论】:
以上是关于设置检查节点检查事件的主要内容,如果未能解决你的问题,请参考以下文章
TVirtualStringTree。如何通过一次确认检查节点及其子节点?
TVirtualStringTree。如何识别用户检查的确切节点?