Я работаю над приложением Excel VBA, которое содержит два элемента управления древовидной структуры, которые содержатся в одной пользовательской форме. Единственное различие между ними состоит в том, что Treeview1 имеет два уровня узлов, а Treeview2 имеет три уровня. Оба дерева используют одинаковые обработчики событий:
BeforeLabelEdit
MouseDown
MouseMove
NodeClick
OLEDragDrop
OLEDragOver
Когда пользователь щелкает мышью узел в treeview1, последовательность событий MouseDown, затем NodeClick. Однако для Treeview2, когда пользователь нажимает на узел, срабатывает только событие NodeClick. После некоторого тестирования я обнаружил, что если я добавлю обработчик события MouseUp для treeview2, он вызовет ПОСЛЕ события NodeClick. Похоже, событие MouseDown никогда не запускается.
Мне интересно, сталкивался ли кто-нибудь с подобной проблемой. Я могу закодировать это, но мне бы очень хотелось понять, почему это происходит. Я предполагаю, что есть кое-что, что я не понимаю о том, как запускаются триггеры событий.
Я использую MouseDown, чтобы захватить выбор мыши и кнопки, и NodeClick, чтобы идентифицировать выбранный узел. Первоначально я использовал обработчик событий MouseDown для (1) захвата нажатий клавиш / клавиш и (2) захвата выбранного узла с помощью функции HitTest. Однако hitTest не захватывал правильный узел, когда я тестировал свое приложение на другом компьютере. Казалось, проще добавить событие NodeClick EventHandler, чем пытаться кодировать обобщенный метод вычисления / преобразования пикселей на разных компьютерах.
Код довольно сложный, поэтому я просто включил обработчики MouseDown и NodeClick для каждого дерева.
Я использую 64-разрядную версию Windows10, версия 1903 и Office 365 (16.0.12026.20344). Я знаю, что в прошлом были проблемы с использованием элементов управления treeview в 64-битной среде, так может ли это быть связано?
Любые мысли очень ценятся.
Спасибо!
'=============================================================
'===== Event Handlers for Treeview 1 =========================
'=============================================================
Private Sub TreeView_LineItem_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, ByVal y As stdole.OLE_YPOS_PIXELS)
gButton = Button
gShift = Shift
End Sub
Private Sub TreeView_LineItem_NodeClick(ByVal Node As MSComctlLib.Node)
Set gSelectedNode = Node
If Not (gSelectedNode Is Nothing) Then
If gShift = 0 Then
If gButton = 1 Then 'Left Mouse
Call Node_Enter(ControlPanel.TreeView_LineItem, gNodeCollLineItems, gNodeGraphLineItems, gSelectedNode)
Set prevSelectedNodeClick = gSelectedNode
Set prevSelectedNodeControl = Nothing
Set prevSelectedNodeShift = Nothing
ControlPanel.TreeView_LineItem.Refresh
If ControlPanel.Visible = False Then
ControlPanel.Show vbModeless
End If
ElseIf gButton = 2 Then 'Right Mouse
'Custom node selected for deletion
If gCustomLineItemDelete = True And gNumCustomLineItems > 1 Then
Call DeleteCustomLineItemStep2(gSelectedNode, ControlPanel.TreeView_LineItem.Nodes)
Application.Goto Reference:=wb.Sheets(1).Range("A1"), Scroll:=True
gCustomLineItemDelete = False
ElseIf gCustomLineItemModify = True And gNumCustomLineItems > 1 Then
Call modifyCustomLineItemStep2(gSelectedNode, ControlPanel.TreeView_LineItem.Nodes)
Application.Goto Reference:=wb.Sheets(1).Range("A1"), Scroll:=True
gCustomLineItemModify = False
'Delete menu line item selected
ElseIf gCustomLineItemDelete = False Or gNumCustomLineItems = 1 Then
If gNumCustomLineItems = 1 Then
MsgBox "There are no custom line items"
End If
For Each cb In CommandBars
If StrComp(cb.name, "LineItem") = 0 Then
cb.Delete
End If
Next
If gCustomLineItemDelete = True Then
GoTo endSub
End If
'Reset menu
Set PopBar = CommandBars.Add(name:="LineItem", Position:=msoBarPopup, MenuBar:=False, Temporary:=True)
Set Top_Menu = PopBar.Controls.Add(Type:=msoControlButton, before:=1, Temporary:=True)
With Top_Menu
.caption = "Clear LineItem Selections"
.OnAction = "ClearLineItemCollections"
End With
PopBar.ShowPopup
End If
End If
ElseIf gShift = 1 Then 'Shift
Call Node_Shift(ControlPanel.TreeView_LineItem, gNodeCollLineItems, gNodeGraphLineItems, gSelectedNode)
Set prevSelectedNodeShift = gSelectedNode
Set prevSelectedNodeControl = Nothing
Set prevSelectedNodeClick = Nothing
ControlPanel.TreeView_LineItem.Refresh
ControlPanel.Show vbModeless
ElseIf gShift = 2 Then 'Cntl
Call Node_Control(ControlPanel.TreeView_LineItem, gNodeCollLineItems, gNodeGraphLineItems, gSelectedNode)
Set prevSelectedNodeControl = gSelectedNode
Set prevSelectedNodeClick = Nothing
Set prevSelectedNodeShift = Nothing
ControlPanel.TreeView_LineItem.Refresh
ControlPanel.Show vbModeless
End If
End If
End Sub
'=============================================================
'===== Event Handlers for Treeview 2 =========================
'=============================================================
Private Sub TreeView_Segment_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As stdole.OLE_XPOS_PIXELS, ByVal y As stdole.OLE_YPOS_PIXELS)
gShift = Shift
gButton = Button
End Sub
Private Sub TreeView_Segment_NodeClick(ByVal Node As MSComctlLib.Node)
set gSelectedNode = Node
gShift = Shift
gButton = Button
If Not (gSelectedNode Is Nothing) Then
If gShift = 0 Then
If gButton = 1 Then 'left mouse
Call Node_Enter(ControlPanel.TreeView_Segment, gNodeCollSegments, gNodeGraphSegments, gSelectedNode)
Set prevSelectedNodeClick = gSelectedNode
Set prevSelectedNodeControl = Nothing
Set prevSelectedNodeShift = Nothing
If ControlPanel.TreeView_Segment.SelectedItem <> gSelectedNode Then
ControlPanel.TreeView_Segment.SelectedItem = gSelectedNode
ControlPanel.TreeView_Segment.DropHighlight = gSelectedNode
End If
ControlPanel.TreeView_Segment.Refresh
ElseIf gButton = 2 Then 'Right Mouse
For Each cb In CommandBars
If StrComp(cb.name, "Segment") = 0 Then
cb.Delete
End If
Next
Set PopBar = CommandBars.Add(name:="Segment", Position:=msoBarPopup, MenuBar:=False, Temporary:=True)
Set Top_Menu = PopBar.Controls.Add(Type:=msoControlButton, before:=1, Temporary:=True)
With Top_Menu
.caption = "Clear Segment Selections"
.OnAction = "ClearSegmentCollections"
End With
PopBar.ShowPopup
End If
ElseIf gShift = 1 Then 'Shift
Call Node_Shift(ControlPanel.TreeView_Segment, gNodeCollSegments, gNodeGraphSegments, gSelectedNode)
Set prevSelectedNodeShift = gSelectedNode
Set prevSelectedNodeControl = Nothing
Set prevSelectedNodeClick = Nothing
If ControlPanel.TreeView_Segment.SelectedItem <> gSelectedNode Then
ControlPanel.TreeView_Segment.DropHighlight = Nothing
End If
ControlPanel.TreeView_Segment.Refresh
ControlPanel.Show vbModeless
ElseIf gShift = 2 Then 'Cntl
Call Node_Control(ControlPanel.TreeView_Segment, gNodeCollSegments, gNodeGraphSegments, gSelectedNode)
Set prevSelectedNodeControl = gSelectedNode
Set prevSelectedNodeClick = Nothing
Set prevSelectedNodeShift = Nothing
If ControlPanel.TreeView_Segment.SelectedItem <> gSelectedNode Then
ControlPanel.TreeView_Segment.SelectedItem = gSelectedNode
End If
ControlPanel.TreeView_Segment.Refresh
ControlPanel.Show vbModeless
End If
End If
endSub:
End Sub