Árvore Nó verificado comportamento em um TreeView em Compact Framework 3.5 em execução no Windows Mobile 6.5

StackOverflow https://stackoverflow.com/questions/1867944

Pergunta

I foram atualizando uma aplicação existente .NET Windows Mobile para usar a versão 3.5 do quadro compacto e para rodar em Windows Mobile 6.5. Eu tenho um formulário com um TreeView. A propriedade TreeView.Checkboxes é definido como verdadeiro para que cada nó tem uma caixa de seleção. Isto dá nenhum problema em todas as versões anteriores do Windows Mobile.

No entanto, na versão 6.5 quando você clica em uma caixa de verificação que aparece para verificar e, em seguida, desmarque instantaneamente. Mas isso só aumenta o evento AfterCheck uma vez. A única maneira que eu posso obter um cheque para vara é clicando duas vezes (o que é o comportamento errado).

Alguém viu esse comportamento? Alguém sabe de uma solução para isso?

Eu incluí uma forma simples teste. Despejar essa forma em um Studio 2008 aplicativo Visual inteligente de dispositivos orientados para o Windows Mobile 6 para ver o que quero dizer.

Public Class frmTree
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
Public Sub New()
    MyBase.new()
    ' This call is required by the Windows Form Designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.

End Sub

'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If disposing AndAlso components IsNot Nothing Then
        components.Dispose()
    End If
    MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
Friend WithEvents TreeView1 As System.Windows.Forms.TreeView
Private mainMenu1 As System.Windows.Forms.MainMenu

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.  
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
    Dim TreeNode1 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node0")
    Dim TreeNode2 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node2")
    Dim TreeNode3 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node3")
    Dim TreeNode4 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node4")
    Dim TreeNode5 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node1")
    Dim TreeNode6 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node5")
    Dim TreeNode7 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node6")
    Dim TreeNode8 As System.Windows.Forms.TreeNode = New System.Windows.Forms.TreeNode("Node7")
    Me.mainMenu1 = New System.Windows.Forms.MainMenu
    Me.TreeView1 = New System.Windows.Forms.TreeView
    Me.SuspendLayout()
    '
    'TreeView1
    '
    Me.TreeView1.CheckBoxes = True
    Me.TreeView1.Location = New System.Drawing.Point(37, 41)
    Me.TreeView1.Name = "TreeView1"
    TreeNode2.Text = "Node2"
    TreeNode3.Text = "Node3"
    TreeNode4.Text = "Node4"
    TreeNode1.Nodes.AddRange(New System.Windows.Forms.TreeNode() {TreeNode2, TreeNode3, TreeNode4})
    TreeNode1.Text = "Node0"
    TreeNode6.Text = "Node5"
    TreeNode7.Text = "Node6"
    TreeNode8.Text = "Node7"
    TreeNode5.Nodes.AddRange(New System.Windows.Forms.TreeNode() {TreeNode6, TreeNode7, TreeNode8})
    TreeNode5.Text = "Node1"
    Me.TreeView1.Nodes.AddRange(New System.Windows.Forms.TreeNode() {TreeNode1, TreeNode5})
    Me.TreeView1.Size = New System.Drawing.Size(171, 179)
    Me.TreeView1.TabIndex = 0
    '
    'frmTree
    '
    Me.AutoScaleDimensions = New System.Drawing.SizeF(96.0!, 96.0!)
    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
    Me.AutoScroll = True
    Me.ClientSize = New System.Drawing.Size(240, 268)
    Me.Controls.Add(Me.TreeView1)
    Me.Menu = Me.mainMenu1
    Me.Name = "frmTree"
    Me.Text = "frmTree"
    Me.ResumeLayout(False)

End Sub
#End Region

End Class
Foi útil?

Solução 2

Eu era capaz de criar uma solução para isso, mas tinha que ir para medidas extremas para fazê-lo. Parece que o comportamento que estamos vendo ocorre porque o evento Click é ser despedido tanto do MouseDown e os eventos MouseUp (em vez de apenas o mouse para cima como ele faria no Windows ou versões anteriores).

Para mostrar isso, você pode começar tocando no caixa, deixando o seu dedo na tela e arrastando a caixa de seleção. Vai tornar-se verificado a partir do evento MouseDown e vai ficar marcada porque o evento MouseUp não é acionado quando você levante o dedo de uma posição diferente. O mesmo funciona para tocar fora da caixa e arrastando.

A fim de evitar o comportamento duplo clique você deve suprimir um dos eventos MouseDown ou MouseUp. I acabou criando um controle que herdou o TreeView e usado WndProcHooker para ligar o método OnMouseDown e marcá-lo como tratado para que o evento MouseDown nunca realmente é demitido. Eu percebi que fez mais sentido (você deve ter o dedo sobre a caixa de seleção ao retirá-lo).

Aqui está um link para o MSDN artigo sobre o WndProcHooker . Abaixo está o meu código para minha classe TreeViewInherit. Enquanto isso funciona, eu ainda estou surpreso que estes são os comprimentos que eu tenho que ir para para começar este trabalho. Além disso, eu não estou ansioso para as correções MS dia isso e, portanto, quebra a minha solução no processo.

    Imports System.Windows.Forms
Imports Microsoft.WindowsCE.Forms

Public Class TreeViewInherit
    Inherits System.Windows.Forms.TreeView

#Region " Variables "
    Private mBlnHandleMouseDown As Boolean
#End Region

#Region " Methods "

    Public Sub New()
    MyBase.New()

    'Set the Handle Mouse Down based on the OS. if 6.5 and up, then handle it.
    mBlnHandleMouseDown = (System.Environment.OSVersion.Version.Major >= 5 AndAlso System.Environment.OSVersion.Version.Minor >= 2 AndAlso System.Environment.OSVersion.Version.Build >= 21234)
    If mBlnHandleMouseDown Then
        WndProcHooker.HookWndProc(Me, New WndProcHooker.WndProcCallback(AddressOf Me.WM_LButtonDown_Handler), Win32.WM_LBUTTONDOWN)
    End If
    End Sub

    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
    'Don't Call the Base to prevent the extra event from firing
    If Not mBlnHandleMouseDown Then
        MyBase.OnMouseDown(e)
    End If
    End Sub

#End Region

#Region " Events "
    Private Function WM_LButtonDown_Handler(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer, ByRef handled As Boolean) As Integer
    Try
        Me.Capture = False

        Dim lastCursorCoordinates As Win32.POINT = Win32.LParamToPoint(lParam)
        If Me.ClientRectangle.Contains(lastCursorCoordinates.X, lastCursorCoordinates.Y) Then
        OnMouseDown(New MouseEventArgs(MouseButtons.Left, 1, lastCursorCoordinates.X, lastCursorCoordinates.Y, 0))
        End If
        handled = True
        Return 0
    Catch ex As Exception
        Throw
    End Try
    End Function
#End Region

End Class

Boa sorte!

Outras dicas

Hydroslide: Para responder à sua primeira pergunta, sim, eu estou vendo esse comportamento. Para sua segunda pergunta: Não, eu ainda tenho que encontrar uma solução

.

Eu desenvolvi um aplicativo em VS2k8 alvo CF 3.5 SP1. Como seu aplicativo, a mina é usado em várias gerações de dispositivos sem problemas. No entanto, eu correr em esta questão TreeView no Windows Mobile 6.5.

Em todos os meus WM 6,5 telefones (o HTC Pure (ST6356), HTC Tilt 2 e HTC Imagio) -, bem como na WM 6.5 emulador - funcionalidade caixa da TreeView falhar. Clicando sobre uma caixa quase sempre causa uma marca de selecção para ser definido apenas para milissegundos mais tarde ser compensados ??(e vice-versa). A única maneira que eu encontrei para forçar de forma confiável uma marca de "pau" é um duplo toque na caixa de seleção. Soa familiar, Hydroslide?

Além deste comportamento bizarro, o aparecimento dessas TreeViews é alterada nos telefones HTC mais recentes para incluem o aumento de espaço em branco entre os nós, presumivelmente para permitir a manipulação mais fácil através de um dedo ou polegar. Compare: @ http://ftp.agconnections.com/treeviews.png . (Remova o @ anterior ao link. Necessário porque StackOverflow primeiro me incentiva a colocar questões que são "detalhado e específico", então me impede de criar um post que inclui mais de um hiperlink. Nice.) Curiosamente, os WM 6,5 emulador exibe as treeview sem qualquer espaço em branco adicional, mas ainda exibe a verificação / problema desmarque.

Eu criei um barebones projeto contendo apenas uma treeview padrão e alguns nós, e seu comportamento é idêntico ao do meu projeto de produção: http://ftp.agconnections.com/TreeViewTest.zip . Eu definir um ponto de interrupção no evento AfterCheck e descobriu - assim como Hydroslide fez -. Que ele só é acionado uma vez quando perfurantes única

Estou surpreso que ninguém fora de nós dois se queixou desse comportamento.

Os clientes à espera de uma correção para este problema estão começando a se acumular, e alguns deles são um pouco menos do que o entendimento. Todas as sugestões são muito apreciados.

Jason Purcell

Para superar o problema do evento AfterCheck não disparando eu descobri que eu poderia fazer o nó clicou e, em seguida, usar isso para chamar AfterCheck, que funciona, mas eu então encontrado AfterCheck foi chamado antes que o estado da caixa de seleção tinha sido mudado assim, em vez levantou o meu próprio evento e tratadas adequadamente.


Imports System.Windows.Forms
Imports Microsoft.WindowsCE.Forms

Public Class TreeViewInherit
    Inherits System.Windows.Forms.TreeView

    'Occurs when the user clicks a TreeNode with the mouse.
    Public Event MouseDownOveride(ByVal node As TreeNode)

#Region " Variables "
    Private mBlnHandleMouseDown As Boolean
#End Region

#Region " Methods "



    Public Sub New()
        MyBase.New()

        'Set the Handle Mouse Down based on the OS. if 6.5 and up, then handle it.
        mBlnHandleMouseDown = (System.Environment.OSVersion.Version.Major >= 5 AndAlso System.Environment.OSVersion.Version.Minor >= 2 AndAlso System.Environment.OSVersion.Version.Build >= 21234)
        If mBlnHandleMouseDown Then
            WndProcHooker.HookWndProc(Me, New WndProcHooker.WndProcCallback(AddressOf Me.WM_LButtonDown_Handler), Win32.WM_LBUTTONDOWN)
        End If
    End Sub

    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        'Don't Call the Base to prevent the extra event from firing
        If Not mBlnHandleMouseDown Then
            MyBase.OnMouseDown(e)
        End If
    End Sub


    Private Function FindTreeNodeFromHandle(ByVal tnc As TreeNodeCollection, ByVal handle As IntPtr) As TreeNode
        For Each tn As TreeNode In tnc
            If tn.Handle = handle Then
                Return tn
            End If
            ' we couldn't have clicked on a child of this node if this node
            ' is not expanded!
            If tn.IsExpanded Then
                Dim tn2 As TreeNode = FindTreeNodeFromHandle(tn.Nodes, handle)
                If tn2 IsNot Nothing Then
                    Return tn2
                End If
            End If
        Next
        Return Nothing
    End Function


#End Region

#Region " Events "
    Private Function WM_LButtonDown_Handler(ByVal hwnd As IntPtr, ByVal msg As UInteger, ByVal wParam As UInteger, ByVal lParam As Integer, ByRef handled As Boolean) As Integer
        Try
            Me.Capture = False

            Dim lastCursorCoordinates As Win32.POINT = Win32.LParamToWin32POINT(lParam)

            If Me.ClientRectangle.Contains(lastCursorCoordinates.X, lastCursorCoordinates.Y) Then
                OnMouseDown(New MouseEventArgs(MouseButtons.Left, 1, lastCursorCoordinates.X, lastCursorCoordinates.Y, 0))
            End If
            handled = True


            Dim msgPos As Point = Win32.LParamToPoint(CInt(Win32.GetMessagePos()))
            msgPos = Me.PointToClient(msgPos)

            ' check to see if the click was on an item
            Dim hti As New Win32.TVHITTESTINFO()
            hti.pt.X = msgPos.X
            hti.pt.Y = msgPos.Y
            Dim hitem As Integer = Win32.SendMessage(Me.Handle, Win32.TVM_HITTEST, 0, hti)
            Dim htMask As UInteger = (Win32.TVHT_ONITEMICON Or Win32.TVHT_ONITEMLABEL Or Win32.TVHT_ONITEMINDENT Or Win32.TVHT_ONITEMBUTTON Or Win32.TVHT_ONITEMRIGHT Or Win32.TVHT_ONITEMSTATEICON)

            If hti.flags = Win32.TVHT_ONITEMSTATEICON Then
                RaiseEvent MouseDownOveride(FindTreeNodeFromHandle(Me.Nodes, hti.hItem))
            End If


            Return 0
        Catch ex As Exception
            Throw
        End Try
    End Function
#End Region

End Class

Obras ok.

Pedimos MS por uma resposta e eles nos deram uma solução alternativa que envolve a captura do clique e marcando ou desmarcando a caixa de seleção conforme desejado. Não tenho cansado ainda, mas se ele faz o trabalho que eu vou postar isso também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top