1

既存の.NETWindowsMo​​bileアプリケーションをアップグレードして、コンパクトフレームワークの3.5バージョンを使用し、WindowsMo​​bile6.5で実行しています。TreeViewのフォームがあります。TreeView.Checkboxesプロパティがtrueに設定されているため、各ノードにチェックボックスがあります。これにより、以前のすべてのバージョンのWindowsMo​​bileで問題が発生することはありません。

ただし、バージョン6.5では、チェックボックスをクリックすると、チェックボックスがオンになり、すぐにオフになります。ただし、AfterCheckイベントは1回だけ発生します。チェックを貼り付ける唯一の方法は、チェックをダブルクリックすることです(これは間違った動作です)。

誰かがこの行動を見たことがありますか?誰かがそれの回避策を知っていますか?

簡単なテストフォームを含めました。このフォームをWindowsMo​​bile6を対象としたVisualStudio2008 Smart Deviceアプリケーションにダンプして、意味を確認します。

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
4

3 に答える 3

1

AfterCheck イベントが発生しないという問題を解決するために、ノードをクリックしてから、それを使用して AfterCheck を呼び出すことができることがわかりました。自分のイベントを適切に処理しました。


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

正常に動作します。

MS に回答を求めたところ、クリックをキャプチャし、必要に応じてチェックボックスをオンまたはオフにする回避策が提供されました。まだ疲れていませんが、うまくいったらそれも投稿します。

于 2010-02-09T10:40:56.457 に答える
1

この代替手段を使用することもできます: http://blogs.southworks.net/mconverti/2009/06/22/optional-checkable-tree-view-control-for-net-compact-framework-35/

于 2010-01-13T22:07:45.947 に答える
1

これに対する回避策を作成することはできましたが、そのために極端な手段を講じる必要がありました。Click イベントが MouseDown イベントと MouseUp イベントの両方から (Windows または以前のバージョンのようにマウスを離すだけではなく) 発生しているため、私たちが目にしている動作が発生しているようです。

これを表示するには、まずチェックボックスをタップし、画面上に指を置いたままチェック ボックスをドラッグします。これは、MouseDown イベントからチェックされるようになり、別の位置から指を離したときに MouseUp イベントが発生しないため、チェックされたままになります。チェックボックスをタップしてドラッグしても同じことが機能します。

ダブルクリックの動作を防ぐには、MouseDown または MouseUp イベントのいずれかを抑制する必要があります。最後に、TreeView を継承するコントロールを作成し、WndProcHooker を使用して OnMouseDown メソッドをフックし、それを処理済みとしてマークして、MouseDown イベントが実際に発生しないようにしました。私はそれが最も理にかなっていると考えました (チェックボックスを持ち上げるときは、チェックボックスの上に指を置く必要があります)。

WndProcHooker に関するMSDN 記事へのリンクを次に示します。以下は、私の TreeViewInherit クラスのコードです。これは機能しますが、これを機能させるにはこれだけの長さの作業が必要であることに今でも驚いています。さらに、MS がこれを修正し、その過程で私の回避策を破る日を楽しみにしていません。

    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

幸運を!

于 2010-01-12T13:23:58.397 に答える