Over in the Classic VB forum I posted some code to enable a context menu for treeview nodes using the keyboard RightClick button. (Located to the right of the spacebar on the keyboard.)
The problem is that I wanted the context menu to appear on top of the selected node, regardless of where the mouse is. The only solution I could come up with was to manually calculate the XY coords of the selected item.
The complete code is reposted below. Note that there is room for a whole lot of improvement. Can we get rid of those nasty constants? Can we handle if the treeview is scrolled to the right? I invite all suggestions for improvement.
The following code goes into the form's module:Edit: The ideal solution would be an API call that returns the selected node's current XY coords. Anyone know how to do that?Code:Private Sub Treeview1_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single) If Button = vbRightButton Then ContextMenu End Sub Private Sub Treeview1_KeyUp(KeyCode As Integer, Shift As Integer) If KeyCode = 93 Then ContextMenu False End Sub ' Note that the form the treeview is on needs to have the same ' font as the treeview. If this is an issue, set the form font at the ' beginning of this function and then set it back on exit. Public Sub ContextMenu(Optional ByVal pblnUseMouseCoords As Boolean = True) Const RowMargin = 3 ' May need to trial & error this value if font changes Const NodeIndent = 19 ' May need to trial & error this one as well Dim nod As MSComctlLib.Node Dim lngRows As Long Dim lngRowHeight As Long Dim lngIndex As Long Dim lngLevel As Long Dim x As Long Dim y As Long With Me If pblnUseMouseCoords Then ' Change mnuMain(6) to the name of your menu .PopupMenu .mnuMain(6) Else ' Determine coords of selected node manually ' Basic height of a node is the height of the font plus the margin lngRowHeight = .TextHeight("X") + (RowMargin * Screen.TwipsPerPixelY) ' Determine how many visible nodes precede the selected one With .Treeview1 ' If no node selected show context menu in upper left of treeview If .SelectedItem Is Nothing Then x = .Left + (NodeIndent \ 2) * Screen.TwipsPerPixelX y = .Top + (lngRowHeight \ 2) Else lngRows = 0 For Each nod In .Nodes If nod.Visible Then lngRows = lngRows + 1 If nod.Index = .SelectedItem.Index Then Exit For End If Next ' Determine how deep the selected node is nested ' This fails acceptably if the treeview is scrolled to the right lngLevel = 0 lngIndex = nod.Index Do While Not (.Nodes(lngIndex).Parent Is Nothing) lngLevel = lngLevel + 1 lngIndex = .Nodes(lngIndex).Parent.Index Loop ' Calculate the coordinates x = .Left + ((NodeIndent \ 2) + (lngLevel * (.Indentation + NodeIndent))) * Screen.TwipsPerPixelX y = .Top + (lngRowHeight * lngRows) - (lngRowHeight \ 2) ' Clear nod object Set nod = Nothing End If End With ' Change mnuMain(6) to the name of your menu .PopupMenu .mnuMain(6), , x, y End If End With End Sub


Reply With Quote