MsComCtlLib Treeview: How to get x,y coordinate of node?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • TheSmileyCoder
    Recognized Expert Moderator Top Contributor
    • Dec 2009
    • 2322

    MsComCtlLib Treeview: How to get x,y coordinate of node?

    I use the Microsoft Common Control Library treeview quite extensively in most of my applications.

    I have coded right click context menus for when a user right clicks a node.

    The default of the popup commandbar is to be shown at the mouse pointer, however its also possible to specify a X and y coordinate.

    Now recently I have tried to add support for keyboard in the treeview and have coded various keyboard actions into the treeview as well, and I can also code it to show the context menu, my problem is that it still displays at the mouse pointer, and since the user isn't using the mouse, that just looks weird.

    So I want the popup to display at the location of the treeview node, but I can't seem to get the coordinate of the node. Does anyone know how to get the x/y coordinate of the node?
  • TheSmileyCoder
    Recognized Expert Moderator Top Contributor
    • Dec 2009
    • 2322

    #2
    I managed to write my own procedure to scan the treeview looking for the selected node, by using the built in hitTest method.

    It could certainly be more efficient if there was a way to simply "ask" the node of its x and y coordinates, since my current method is like asking in the blind trying to hit the right node.

    Code:
    Public Function GetProjectNodeCoordinates(ByRef x As Long, ByRef y As Long) As Boolean
    'Get the x and y coordinate of the selected node in the Treeview Projects on the main form
    
    
       'Variables
          Dim nodX As MSComctlLib.Node
          Dim nodZ As MSComctlLib.Node
          Dim lngX As Long
          Dim lngY As Long
       
       'Get selected node
          Set nodX = Forms("frm_Main")!TreeProjects.Object.SelectedItem
       
       'If No node selected, exit
          If nodX Is Nothing Then Exit Function
       
       'Loop over treview trying to find selected node
       With Forms("frm_Main").TreeProjects.Object
          For lngX = 50 To 5000 Step 50
             For lngY = 50 To 50000 Step 50
                'Try a hittest
                   Set nodZ = .HitTest(lngX, lngY)
                'If we hit nothing skip the comparison and proceed to next for loop
                   If Not nodZ Is Nothing Then
                      'Compare hit node to selected node
                      If nodZ.Key = nodX.Key Then
                         'We found the selected node
                            x = lngX
                            y = lngY
                            GetProjectNodeCoordinates = True
                            Exit Function
                      End If
                   End If
             Next
          Next
       End With
    End Function
    Note: The x and y coordinates of the treeview is internal and starts at 0,0 in the upper left corner. Furthermore they seem to scale differently then the x and y coordinates of the screen. More on this later.


    That alone is however not enough, since I also need to find the screen x and y of the treeview control itself. To do this I use a API call:
    Code:
    Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
    End Type
    Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
     
    Public Sub GetCtrlCoord(ctrl As Control, ByRef x As Long, ByRef y As Long)
       Dim Rec As RECT
        GetWindowRect ctrl.hWnd, Rec
        x = Rec.Left
        y = Rec.Top
    End Sub

    So to get the x and y of my treeview control I do:
    Code:
      Dim xTV As Long
      Dim yTV As Long
      Call GetCtrlCoord(Forms("frm_Main")!TreeProjects, xTV, yTV)


    As I said the treeviews internal x and y seem to differ from the external screen x and y, and by trial and error I seem to have found the correct "conversion ":
    Code:
    x = x / 15
    y = y / 15 + 20
    The +20 for the y is simply because I find it looks nice to move it down bit so that the menu doesn't display on top of the node, blocking the text.


    To sum it all up, when the user presses shift enter while the treeview is active I do:
    Code:
    Dim X as long
    Dim y as long
    Dim xTV as long
    dim yTV as long
    
    If GetProjectNodeCoordinates(x, y) Then
      Call GetCtrlCoord(xTv,yTV)
      cmdBar.ShowPopup x + xTV, y + yTV
    End If
    Where cmdBar is a commandbar declared elsewhere.

    Comment

    Working...