Node tree Controllato comportamento su un TreeView in Compact Framework 3.5 in esecuzione su Windows Mobile 6.5

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

Domanda

Sono stato l'aggiornamento di un applicazione .NET Windows Mobile esistente per utilizzare la versione 3.5 del framework compatto e per l'esecuzione su Windows Mobile 6.5. Ho una forma con un TreeView. La struttura TreeView.Checkboxes è impostata su true in modo che ciascun nodo ha una casella di controllo. Questo dà alcun problema in tutte le versioni precedenti di Windows Mobile.

Tuttavia, nella versione 6.5, quando si fa clic su una casella di controllo appare per controllare e quindi deselezionare istantaneamente. Ma solleva solo l'evento AfterCheck una volta. L'unico modo per ottenere un assegno a bastone è con un doppio clic su di esso (che è il comportamento sbagliato).

Qualcuno ha visto questo comportamento? Qualcuno sa di una soluzione per esso?

Ho incluso un semplice modulo di prova. Dump questa forma in un Visual Studio 2008 applicazione Smart Device destinati a Windows Mobile 6 per vedere quello che voglio dire.

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
È stato utile?

Soluzione 2

Sono stato in grado di creare una soluzione per questo, ma doveva andare a misure estreme per farlo. Sembra che il comportamento che stiamo vedendo si verifica perché l'evento Click viene licenziato sia dal MouseDown e gli eventi MouseUp (invece di appena il mouse in alto come sarebbe in Windows o versioni precedenti).

Per dimostrare questo, si può iniziare toccando la casella di controllo, lasciando il dito sullo schermo e trascinando fuori la casella di controllo. Diventerà controllato dall'evento MouseDown e rimarrà controllato perché l'evento MouseUp non viene generato quando si solleva il dito da una posizione diversa. Le stesse opere per maschiatura fuori la casella di controllo e trascinando via.

Al fine di evitare che il comportamento doppio click è necessario sopprimere uno degli eventi MouseDown o MouseUp. Ho finito per la creazione di un controllo che ha ereditato il controllo TreeView e utilizzato WndProcHooker per agganciare il metodo OnMouseDown e segnare come maneggiato in modo che l'evento MouseDown mai effettivamente viene licenziato. Ho pensato che ha reso più senso (è necessario avere il dito sopra la casella di controllo quando si solleva).

Questo è il link al MSDN articolo sulla WndProcHooker . Qui di seguito è il mio codice per la mia classe TreeViewInherit. Anche se questo funziona, io sono ancora stupito che queste sono le lunghezze che devo andare in per ottenere questo lavoro. Inoltre, io non vedo l'ora di giorno MS corregge questo e, quindi, spezza il soluzione nel 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

Buona fortuna!

Altri suggerimenti

Hydroslide: Per rispondere alla tua prima domanda, sì, sto vedendo questo comportamento. Per la tua seconda domanda: No, non ho ancora trovato una soluzione

.

Ho sviluppato un app in VS2K8 mira CF 3.5 SP1. Come la vostra applicazione, il mio è utilizzato su diverse generazioni di dispositivi senza problemi. Tuttavia, ho incontrato questo problema TreeView su Windows Mobile 6.5.

Su tutto il mio WM 6.5 telefoni (l'HTC Pure (ST6356), HTC Tilt 2 e HTC Imagio) - così come nel WM 6.5 emulatore - funzionalità casella di controllo del controllo TreeView fallisce. Cliccando su una casella di controllo quasi provoca sempre un segno di spunta da impostare millisecondi solo per essere eliminato in seguito (e viceversa). L'unico modo che ho trovato per forzare in modo affidabile un segno di spunta a "bastone" è quello di toccare due volte-la casella di controllo. Suona familiare, Hydroslide?

In aggiunta a questo comportamento bizzarro, la comparsa di questi TreeViews viene alterato sui telefoni più recenti HTC per includere aumentato lo spazio bianco tra i nodi, probabilmente per consentire la più agevole la manipolazione tramite un dito o il pollice. Confronto: @ http://ftp.agconnections.com/treeviews.png . (Rimuovere il @ precede il link. Necessario perché StackOverflow mi incoraggia primo a postare domande che sono "dettagliate e specifiche", quindi mi impedisce di creare un post che include più di un collegamento ipertestuale. Bel.) È interessante notare che l'emulatore WM 6.5 visualizza la TreeView senza alcun spazio bianco aggiuntivo, ma ancora presenta il controllo / deselezionare problema.

Ho creato un progetto barebone che contiene solo una vista ad albero standard e un paio di nodi, e il suo comportamento è identico a quello del mio progetto di produzione: http://ftp.agconnections.com/TreeViewTest.zip . Ho impostato un punto di interruzione in caso AfterCheck ed ho trovato - proprio come fece Hydroslide -. Che è sparato solo una volta quando single-intercettazioni

Sono stupito che nessuno al di fuori di noi due ha lamentato di questo comportamento.

I clienti in attesa di una correzione per questo problema stanno cominciando ad accumularsi, e alcuni di loro sono un po 'meno-che-comprensione. Tutti i suggerimenti sono molto apprezzate.

Jason Purcell

Per superare il problema della manifestazione AfterCheck non sparare ho scoperto che avrei potuto ottenere il nodo cliccato e quindi utilizzare tale per chiamare AfterCheck, che funziona ma poi ho trovato AfterCheck è stato chiamato prima che lo stato della casella di controllo era stato cambiato così invece sollevato il mio caso e gestito in modo appropriato.


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

funziona bene.

Abbiamo chiesto MS per una risposta e ci hanno dato una soluzione che prevede l'acquisizione del clic e selezionando o deselezionando la casella di controllo, se lo desideri. Non hanno ancora stanco, ma se lo fa il lavoro posterò anche quello.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top