多次快速单击时复选框无法正常工作 [英] CheckBox not work properly when clicked on quickly multiple times

查看:25
本文介绍了多次快速单击时复选框无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这段代码的作用:

  1. 如果父节点被选中/取消选中,还要选中/取消选中所有子节点.

  1. If parent node is checked/unchecked, also check/uncheck all child nodes.

如果只检查了一个子节点,还要检查父节点.

If just one child node is checked, also check parent node.

Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck
    If updatingTreeView Then Return
    updatingTreeView = True
    CheckNode(e.Node, e.Node.Checked)
    HasCheckedChildNode = 0
    updatingTreeView = False
End Sub

Private Sub CheckNode(node As TreeNode, isChecked As Boolean)如果 node.Parent IsNot Nothing 那么HasCheckedNode(node.Parent)如果没有 isChecked 并且 HasCheckedChildNode > 0 然后返回node.Parent.Checked = isCheckedElseIf node.Parent Is Nothing Then对于每个 cn 作为 TreeNode 在 node.Nodescn.Checked = isChecked下一个万一结束子

Private Sub CheckNode(node As TreeNode, isChecked As Boolean) If node.Parent IsNot Nothing Then HasCheckedNode(node.Parent) If Not isChecked And HasCheckedChildNode > 0 Then Return node.Parent.Checked = isChecked ElseIf node.Parent Is Nothing Then For Each cn As TreeNode In node.Nodes cn.Checked = isChecked Next End If End Sub

私有子HasCheckedNode(node As TreeNode)对于每个 cn 作为 TreeNode 在 node.Nodes如果 cn.Checked = True 那么HasCheckedChildNode += 1ElseIf cn.Checked = False 那么HasCheckedChildNode -= 0万一下一个结束子

Private Sub HasCheckedNode(node As TreeNode) For Each cn As TreeNode In node.Nodes If cn.Checked = True Then HasCheckedChildNode += 1 ElseIf cn.Checked = False Then HasCheckedChildNode -= 0 End If Next End Sub

此代码工作正常.

问题:

当我快速点击时,有些复选框被选中,有些没有例如.有时我检查了父节点,但所有子节点仍然未选中.有时父节点未选中但其子节点仍选中.

When I clicks quickly some of the checkboxes are checked and some no E.g. Sometimes I checked the parent node but all child nodes still remain unchecked. Sometimes the parent node is unchecked but its child nodes still checked.

请检查示例图片:

如何解决这个问题,这是我电脑的问题吗?

How to solve this, is this a problem with my PC?

推荐答案

发生这种情况是因为 TreeView 默认情况下不会在鼠标双击复选框时切换 TreeNode 对象的 Check 属性区域.您需要拦截WM_LBUTTONDBLCLK 消息,获取双击点的TreeViewHitTestInfo,如果双击点超过了,则切换Check 属性复选框.

That happens because the TreeView by default doesn't toggle the Check property of the TreeNode objects on mouse double click over the check box area. You need to intercept the WM_LBUTTONDBLCLK messages, get TreeViewHitTestInfo of the double clicked point, and toggle the Check property if the double clicked point is over the check box.

这是一个自定义的 TreeView,它也解决了主要问题,检查/取消检查分支的父节点和子节点,只需启用 AutoCheckParents 和/或 AutoCheckChildren 属性.

Here's a custom TreeView for that, also it solves the main issue, checking/unchecking the parent and child nodes of the branch, just enable the AutoCheckParents and/or AutoCheckChildren properties for that.

Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

<DesignerCategory("Code")>
Public Class DoubleClickCheckTreeView
    Inherits TreeView

#Region "Properties"

    <Category("Behavior"),
        DefaultValue(False)>
    Public Property AutoCheckParents As Boolean = False

    <Category("Behavior"),
        DefaultValue(False)>
    Public Property AutoCheckChildren As Boolean = False

#End Region

#Region "Overrides"

    'Enable DoubleBuffered to reduce the flickering.
    Protected Overrides Sub OnHandleCreated(e As EventArgs)
        SendMessage(Handle,
                    TVM_SETEXTENDEDSTYLE,
                    IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER),
                    IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER))
        MyBase.OnHandleCreated(e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        If m.Msg = WM_LBUTTONDBLCLK AndAlso CheckBoxes Then
            Dim x As Integer = m.LParam.ToInt32() And &HFFFF
            Dim y As Integer = (m.LParam.ToInt32 >> 16) And &HFFFF
            Dim ht As TreeViewHitTestInfo = HitTest(x, y)

            If ht.Node IsNot Nothing AndAlso
                ht.Location = TreeViewHitTestLocations.StateImage Then
                OnBeforeCheck(New TreeViewCancelEventArgs(ht.Node,
                                                          False,
                                                          TreeViewAction.ByMouse))
                ht.Node.Checked = Not ht.Node.Checked
                OnAfterCheck(New TreeViewEventArgs(ht.Node, TreeViewAction.ByMouse))
                m.Result = IntPtr.Zero
                Return
            End If
        End If
        MyBase.WndProc(m)
    End Sub

    Protected Overrides Sub OnAfterCheck(e As TreeViewEventArgs)
        MyBase.OnAfterCheck(e)

        If e.Action = TreeViewAction.Unknown OrElse
            Not CheckBoxes Then Return

        If AutoCheckParents Then
            Dim p = e.Node.Parent

            While p IsNot Nothing
                p.Checked = p.Nodes.Cast(Of TreeNode).Any(Function(x) x.Checked)
                p = p.Parent
            End While
        End If

        If AutoCheckChildren Then
            For Each tn As TreeNode In GetNodes(e.Node)
                tn.Checked = e.Node.Checked
            Next
        End If
    End Sub

#End Region

#Region "Private Methods"

    Private Iterator Function GetNodes(node As TreeNode) As IEnumerable(Of TreeNode)
        For Each n As TreeNode In node.Nodes
            Yield n
            For Each c As TreeNode In GetNodes(n)
                Yield c
            Next
        Next
    End Function

#End Region

#Region "API"

    Private Const TVM_SETEXTENDEDSTYLE As Integer = &H1100 + 44
    Private Const TVM_GETEXTENDEDSTYLE As Integer = &H1100 + 45
    Private Const TVS_EX_DOUBLEBUFFER As Integer = &H4
    Private Const WM_LBUTTONDBLCLK As Integer = &H203

    <DllImport("user32.dll")>
    Private Shared Function SendMessage(ByVal hWnd As IntPtr,
                                       ByVal msg As Integer,
                                       ByVal wp As IntPtr,
                                       ByVal lp As IntPtr) As IntPtr
    End Function

#End Region

End Class

  • 向您的项目添加一个新类并粘贴此代码.
  • 重建.
  • 删除 DoubleClickCheckTreeView 的实例或更改设计器中现有默认 TreeView 的类型.
  • 相关

    <小时>

    TreeView、Windows 窗体 (c#) 中的 AfterCheck 和 AfterSelect 事件

    这篇关于多次快速单击时复选框无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆