Display hourglass cursor while expanding ExplorerTree node

Share your advanced PureBasic knowledge/code with the community.
User avatar
Shardik
Addict
Addict
Posts: 2060
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Display hourglass cursor while expanding ExplorerTree node

Post by Shardik »

Code updated For 5.20+

Some of my customers have complained using some of my PureBASIC applications with ExplorerTreeGadgets when expanding a folder node with lots of files. The ExplorerTreeGadget doesn't switch to an hourglass cursor if you klick on a plus to expand a folder with lots of files or a partition with lots of folders. Especially on older PCs it seems to happen nothing for a while after the klick on the plus sign.

Thanks to srod's unbelievable EasyVENT library (http://www.purebasic.fr/english/viewtopic.php?t=21136) the solution is a snap:

Code: Select all

;*********************************************************************************
XIncludeFile "C:\Programme\EasyVENT\EasyVENT.PBI"
;*********************************************************************************

Declare ExpandCollapse(*Sender.PB_Sender)
Declare SetCursor(*Sender.PB_Sender)
Define WaitCursorHandle

OpenWindow(0, 0, 0, 300, 250, "ExplorerTree with hourglass cursor", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ExplorerTreeGadget(0, 10, 10, 280, 230, "C:\")

; ----- Set event handlers

SetEventHandler(GadgetID(0), #OnCollapseExpandSelection, @ExpandCollapse())
SetEventHandler(GadgetID(0), #OnSetCursor, @SetCursor())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

End

;*********************************************************************************
;                                 EVENT HANDLERS
;*********************************************************************************

Procedure ExpandCollapse(*Sender.PB_Sender)
  Shared WaitCursorHandle
  
  If *Sender\State = #EVENT_EXPAND
    WaitCursorHandle = LoadCursor_(0, #IDC_WAIT)
    SetCursor_(WaitCursorHandle)
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


Procedure SetCursor(*Sender.PB_Sender)
  Shared WaitCursorHandle
  
  If WaitCursorHandle <> 0
    DestroyCursor_(WaitCursorHandle)
    WaitCursorHandle = 0
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Thank you very much srod for sharing your invaluable lib EasyVENT with all sources. My programming life has become a lot easier :wink:
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

You're welcome Shardik.

By the way, you don't need the #OnSetCursor handler for this particular example as I think that PB locks the cursor when the ExplorerTree gadget is rummaging around the disc anyhow. So you only need the CollapseExpand handler in this case. :)

Also, you shouldn't use DestroyCursor_() on a cursor loaded with LoadCursor_(). It's for those created with CreateCursor_() only.
I may look like a mule, but I'm not a complete ass.
Tranquil
Addict
Addict
Posts: 952
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Post by Tranquil »

thanks Shardik for sharing theseone. Its a nice idea displaying the clock.
Often I perform SQL Queries while expanding a treegadget node and this takes some time. So it makes sense to display a clockpointer. :)
Tranquil
User avatar
Shardik
Addict
Addict
Posts: 2060
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

Thank you srod for pointing out that #OnSetCursor isn't required and DestroyCursor_() shouldn't be used. The resulting code becomes even shorter:

Code: Select all

;*********************************************************************************
XIncludeFile "C:\Programme\EasyVENT\EasyVENT.PBI"
;*********************************************************************************

Declare.L ExpandCollapse(*Sender.PB_Sender)

OpenWindow(0, 0, 0, 300, 250, "ExplorerTree with hourglass cursor", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ExplorerTreeGadget(0, 10, 10, 280, 230, "C:\") 
      
; ----- Set event handlers

SetEventHandler(GadgetID(0), #OnCollapseExpandSelection, @ExpandCollapse())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

End

;*********************************************************************************
;                                 EVENT HANDLERS
;*********************************************************************************

Procedure ExpandCollapse(*Sender.PB_Sender)
  Shared WaitCursorHandle.L

  If *Sender\State = #EVENT_EXPAND
    SetCursor_(LoadCursor_(0, #IDC_WAIT))
  EndIf

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
For those of you who don't want to include srod's wonderful EasyVENT library in your code I have built a stripped down version with only the essentials from srod's library. But for bigger projects you should nevertheless give EasyVENT a try... :wink:

Code: Select all

Procedure WindowCallback(hWindow.L, uMsg.L, wParam.L, lParam.L)
  *NMH.NMHDR
  *NMTV.NM_TREEVIEW

  If hWindow = WindowID(1)
    If uMsg = #WM_NOTIFY
      *NMH = lParam

      If *NMH\hwndFrom = GadgetID(1)
        If *NMH\code = #TVN_ITEMEXPANDING
          *NMTV = lParam
 
          If *NMTV\action = #TVE_EXPAND
            SetCursor_(LoadCursor_(0, #IDC_WAIT))
          EndIf
        EndIf
      Endif  
    EndIf
  EndIf

  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure


OpenWindow(1, 0, 0, 300, 250, "ExplorerTree with hourglass cursor", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(1))
ExplorerTreeGadget(1, 10, 10, 280, 230, "C:\") 

SetWindowCallback(@WindowCallback(), 1) 

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Update: Added a check for the correct gadget
Last edited by Shardik on Tue Jun 13, 2006 9:39 am, edited 2 times in total.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Nice indeed.

thanks to both of you.

cheers
User avatar
Shardik
Addict
Addict
Posts: 2060
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

For those of you who still work (or have to work) with trusty old PB 3.9x I have programmed an adapted version. The above standalone version (without EasyVENT) for PB 4 doesn't work for PB 3.9x because the explorer type gadgets seem to have changed their callback behaviour (I had to learn it the hard way... :wink: ). Freak described in a post from 2004
viewtopic.php?t=9502
that explorer type gadgets in PB 3.9x have to be subclassed:
The Explorer type gadgets have a special parent window to process their
messages. That's why such a message never makes it into the main
callback.

You have to subclass the imediate parent of the gadget in order to get
such messages.
This is the PB 3.9x version:

Code: Select all

Procedure WindowCallback(hWindow.L, uMsg.L, wParam.L, lParam.L)
  Shared OldCallback.L

  If uMsg = #WM_NOTIFY
    *NMH.NMHDR = lParam

    If *NMH\hwndFrom = GadgetID(1)
      If *NMH\code = #TVN_ITEMEXPANDING
        *NMTV.NM_TREEVIEW = lParam

        If *NMTV\action = #TVE_EXPAND
          SetCursor_(LoadCursor_(0, #IDC_WAIT))
        EndIf
      EndIf
    EndIf
  EndIf

  ProcedureReturn CallWindowProc_(OldCallback, hWindow, uMsg, wParam, lParam)
EndProcedure


OpenWindow(1, 0, 0, 300, 250, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "ExplorerTree with hourglass cursor")
CreateGadgetList(WindowID(1))
ExplorerTreeGadget(1, 10, 10, 280, 230, "C:\") 

OldCallback = SetWindowLong_(GetParent_(GadgetID(1)), #GWL_WNDPROC, @WindowCallback())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Post Reply