Page 1 of 1

Activating dead left click zones in a TreeGadget

Posted: Fri Mar 03, 2006 3:26 am
by Sparkie
Code updated For 5.20+

Left clicking to the left or right of the item text in a TreeGadget text does not select that item. This is a Windows feature by design.

For TreeGadgets that DO NOT use the #PB_Tree_NoLines flag, you need to catch the #NM_CLICK message and then send a #TVM_HITTEST message to see which item row was clicked. This is demonstrated with the left side TreeGadget (#Tree_Lines_Yes).

For TreeGadgets that DO use the #PB_Tree_NoLines flag, you can add the #TVS_FULLROWSELECT flag using SetWindowLong_(). This is demonstrated with the right side TreeGadget (#Tree_Lines_No).

Code: Select all

;/=========================================================================
;/ Code      : TreeGadget - left click anywhere on item row selects item
;/ Author    : Sparkie
;/ Start Date: 03/02/06
;/ PB Version: PB 4.00
;/ OS Support: Windows 98/NT/ME/2000/XP/Server 2003
;/==========================================================================

;/===============================================
;/ Constants / Enumerations
;/===============================================
;...TreeGadget style constant
#TVS_FULLROWSELECT = $1000

;...TreeGadget enumeration
#Tree_Lines_Yes = 0
#Tree_Lines_No = 1

;...Window enumeration
#Win_Main = 0

;/==========================================================================
;/ Procedure - Window Callback
;/==========================================================================
Procedure WinCallback(hwnd, msg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select msg
    Case #WM_NOTIFY
      *pnmhdr.NMHDR = lParam
      Select *pnmhdr\code
          ;...It's a left click
        Case #NM_CLICK
          Select *pnmhdr\hwndFrom
              ;...Is it from our TreeGadget that has lines?
            Case GadgetID(#Tree_Lines_Yes)
              ;...We will need to convert screen mouse x/y to TreeGadget x/y
              screenPt.POINT
              screenPt\x = DesktopMouseX()
              screenPt\y = DesktopMouseY()
              ScreenToClient_(*pnmhdr\hwndFrom, @screenPt)
              tvht.TV_HITTESTINFO
              tvht\pt\x = screenPt\x
              tvht\pt\y = screenPt\y
              ;...Get the area that is clicked
              SendMessage_(*pnmhdr\hwndFrom, #TVM_HITTEST, 0, @tvht)
              ;...If the area is to the right or left of the item
              If tvht\flags = #TVHT_ONITEMRIGHT Or tvht\flags = #TVHT_ONITEMINDENT
                ;...Select that item
                SendMessage_(*pnmhdr\hwndFrom, #TVM_SELECTITEM, #TVGN_CARET, tvht\hItem)
              EndIf
          EndSelect
      EndSelect
  EndSelect
  ProcedureReturn result
EndProcedure
;/==========================================================================
;/ Main Window
;/==========================================================================
If OpenWindow(#Win_Main, 0, 0, 355, 220,"TreeGadget Fullrow Select", #PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
  SetWindowCallback(@WinCallback())
  
  ;...TreeGadgets that have lines between nodes (default)
  ;   cannot use the #TVS_FULLROWSELECT style. We handle
  ;   fullrow selection in our callback.
  TreeGadget(#Tree_Lines_Yes, 10, 10, 160, 160)
  
  ;...TreeGadgets that DO NOT have lines between nodes (#PB_Tree_NoLines)
  ;   can use the #TVS_FULLROWSELECT style.
  TreeGadget(#Tree_Lines_No, 180, 10, 160, 160, #PB_Tree_CheckBoxes | #PB_Tree_NoLines)
  SetWindowLong_(GadgetID(#Tree_Lines_No), #GWL_STYLE, GetWindowLong_(GadgetID(#Tree_Lines_No), #GWL_STYLE) | #TVS_FULLROWSELECT)
  
  For t = #Tree_Lines_Yes To #Tree_Lines_No
    For i = 0 To 10
      AddGadgetItem (t, -1, "Normal Item " + Str(i), 0, 0)
      AddGadgetItem (t, -1, "Node " + Str(i), 0, 0)
      AddGadgetItem(t, -1, "Sub-Item 1", 0, 1)
      AddGadgetItem(t, -1, "Sub-Item 2", 0, 1)
      AddGadgetItem(t, -1, "Sub-Item 3", 0, 1)
      AddGadgetItem(t, -1, "Sub-Item 4", 0, 1)
      AddGadgetItem (t, -1, "File " + Str(i), 0, 0)
    Next i
  Next t
  
  Repeat
    event = WaitWindowEvent()
  Until event = #PB_Event_CloseWindow
EndIf
End