2009-12-08 1 views
1

Compact Framework의 3.5 버전을 사용하고 Windows Mobile 6.5에서 실행되도록 기존 .NET Windows Mobile 응용 프로그램을 업그레이드했습니다. TreeView있는 폼이 있습니다. 각 노드에 확인란이 있도록 TreeView.Checkboxes 속성이 true로 설정됩니다. 이전 버전의 Windows Mobile에서도 문제없이 사용할 수 있습니다.트리 노드 Windows Mobile 6.5에서 실행되는 Compact Framework 3.5의 TreeView에서 동작 확인

그러나 버전 6.5에서는 확인란을 클릭하면 즉시 확인하고 선택을 취소 한 것처럼 보입니다. 그러나 AfterCheck 이벤트는 한 번만 발생합니다. 내가 수표를 얻을 수있는 유일한 방법은 그것을 두 번 클릭하는 것입니다 (이것은 잘못된 행동입니다).

이 동작을 본 사람이 있습니까? 누구든지 해결 방법을 알고 있습니까?

간단한 테스트 양식이 포함되어 있습니다. 이 양식을 Windows Mobile 6을 대상으로하는 Visual Studio 2008 스마트 장치 응용 프로그램으로 덤프하여 의미를 확인하십시오.

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 

답변

1

나는 이것에 대한 해결 방법을 만들 수 있었지만 그렇게 극단적 인 조치로 이동했다. Click 이벤트가 MouseDown 및 MouseUp 이벤트 (Windows 또는 이전 버전 에서처럼 마우스를 위로 움직이지 않고)에서 발생하기 때문에 발생하는 것으로 보입니다.

이것을 표시하려면 체크 박스를 탭하고 화면에 손가락을두고 체크 박스를 드래그하여 시작할 수 있습니다. MouseDown 이벤트에서 확인되고 다른 위치에서 손가락을 뗄 때 MouseUp 이벤트가 발생하지 않기 때문에 검사 ​​상태를 유지합니다. 체크 박스를 가볍게 두드리고 드래그하여도 똑같이 작동합니다.

두 번 클릭 동작을 방지하려면 MouseDown 또는 MouseUp 이벤트 중 하나를 억제해야합니다. TreeView를 상속 한 WndProcHooker를 사용하여 OnMouseDown 메서드를 연결하고 MouseDown 이벤트가 실제로 실행되지 않도록 처리 된 것으로 표시하는 컨트롤을 만드는 작업이 끝났습니다. 나는 그것이 가장 이해가된다고 생각했다 (당신이 그것을 들어 올릴 때 당신은 체크 박스 위에 당신의 손가락을 가져야한다).

여기 WndProcHooker에 대한 MSDN article에 대한 링크가 있습니다. 아래 내 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 

행운을 비네!

+0

MSDN 설명서의 WndProcHooker에 링크 된 CompactFramework 3.5에서 질문에 대한 질문이 컴파일되지 않습니다. –

+0

"유형 또는 네임 스페이스 'Win32'를 찾을 수 없습니다 (사용 지시문 또는 어셈블리 참조가 누락 되었습니까?)". 흠 ... 사용 또는 어셈블리 참조가 누락 되었다면 알고 싶습니다. 불행히도 MSDN의 코드는 지시문 사용 중 표시하지 않으며 사용 가능한 어셈블리 참조가 표시되는 다운로드 가능한 솔루션이 없습니다. . 게다가 전체 .NET Framework를위한 것이라고 생각합니다. 아마도 이것이 작동하지 않는 이유 일 것입니다. –

+0

여기'Win32' 클래스가 컴파일 해주었습니다 : http://blogs.msdn.com/b/netcfteam/archive/2005/05/20/420551.aspx –

1

하이드로 슬라이드 : 첫 번째 질문에 대답하려면 네,이 동작을보고 있습니다. 두 번째 질문 : 아니오, 아직 해결책을 찾지 못했습니다.

저는 CF 3.5 SP1을 대상으로하는 VS2K8 앱을 개발했습니다. 귀하의 앱과 마찬가지로, 광산은 여러 세대의 기기에 문제없이 사용됩니다. 그러나 Windows Mobile 6.5에서이 TreeView 문제가 발생했습니다.

WM 6.5 에뮬레이터와 마찬가지로 모든 WM 6.5 전화기 (HTC Pure (ST6356), HTC Tilt 2 및 HTC Imagio)에서 TreeView의 확인란 기능이 실패합니다. 체크 상자를 클릭하면 거의 항상 체크 표시가 밀리 초 후에 만 ​​지워지도록 설정됩니다 (반대의 경우도 마찬가지입니다). 내가 확실하게 "스틱"에 체크 표시를 강제로 발견했습니다 유일한 방법은 두 번 누릅니다 체크 박스이다. 익숙한 소리, Hydroslide?

이러한 기괴한 동작 외에도 노드 사이에 증가 된 공백을 포함하도록 아마도이 손가락 모양이나 엄지 손가락을 통해보다 쉽게 ​​조작 할 수 있도록 새 HTC 폰에서 이러한 TreeView의 모양이 변경됩니다. 비교 : @http://ftp.agconnections.com/treeviews.png. (StackOverflow가 먼저 "상세하고 구체적인"질문을 게시하도록 권장하므로 하나 이상의 하이퍼 링크가 포함 된 게시물을 만들지 않게됩니다.) Nice.) 흥미롭게도 WM 6.5 에뮬레이터는 추가 공백없이 트리 뷰를 표시하지만 여전히 점검/선택 취소 문제점을 표시합니다.

저는 표준 treeview와 몇 개의 노드 만 포함하는 barebones 프로젝트를 만들었으며 그 동작은 내 프로덕션 프로젝트의 동작과 동일합니다 : http://ftp.agconnections.com/TreeViewTest.zip. AfterCheck 이벤트에서 중단 점을 설정하고 Hydroslide처럼 중단 점을 설정했습니다. 단일 탭을 한 번만 누르면 실행됩니다.

나는 우리 둘 밖에 아무도이 문제의 불평했다고 놀라게 해요. 이 문제에 대한 수정을 기다리고

고객의가 쌓이기 시작하고, 그들 중 몇은 다소-보다 적게보다는 이해입니다. 어떤 제안이라도 대단히 감사하겠습니다.

제이슨 퍼셀

1

은 내가 AfterCheck를 호출하는 것을 사용 후 노드가 클릭 얻을 수 있다는 것을 발견 발사하지 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에 답변을 요청했으며 클릭을 캡처하고 필요에 따라 확인란을 선택 또는 선택 취소하는 등의 해결 방법을 제공했습니다. 아직 피곤하지 않았지만 그것이 일을하는 경우에도 나는 그것을 게시 할 것입니다.

+0

'WndProcHooker'는 어디에서 왔습니까? –

관련 문제