Page 1 of 2

ScrollBar With Tracking

Posted: Sun Jan 20, 2013 8:04 am
by Psych
Much discussion about this on the forums so I thought I'd share my solution to tracking scrollbar changes when the thumb is moved. Although this is a windows only solution, I found the other solutions to be a little bloated.
I tried using the 'gadget event hack' to send the event as a change event type but all it did was queue the events and fire them all at once when the mouse button was released (much to my annoyance, I should have known better, I went through all this when I was dismayed at why the windowevent blocks on window movement). I also tried to disable the arrows based on position, but they just get re-enabled (again, much to my annoyance).
I wrote this mainly because I wanted a solution that didn't require setting a callback for the whole window, but I guess if you have a callback anyway, it wouldn't matter.
Functions use window props, so no need to keep a track of default window callbacks, etc.

Code: Select all

Procedure ScrollProc(SbarID,Msg,wParam,*lParam.SCROLLINFO)
  With *lParam
    Protected result,*defproc=GetProp_(SbarID,@"scrollbar_winproc")
    If *defproc
      result=CallWindowProc_(*defproc,SbarID,Msg,wParam,*lParam)
    EndIf
    If Msg=#SBM_SETSCROLLINFO And *lParam
      If Not \nPos=GetProp_(SbarID,@"scrollbar_value")
        SetProp_(SbarID,@"scrollbar_value",\nPos)
        Debug \nPos
      EndIf
    EndIf
    ProcedureReturn result
  EndWith
EndProcedure
Procedure SmoothScrollBarGadget(Gadget,x,y,Width,Height,Min,Max,PageLength,flags=0)
  Protected hwnd,gid=ScrollBarGadget(Gadget,x,y,Width,Height,Min,Max,PageLength,flags)
  hwnd=gid
  If Gadget=#PB_Any
    hwnd=GadgetID(gid)
  EndIf
  SetProp_(hwnd,@"scrollbar_winproc",SetWindowLongPtr_(hwnd,#GWLP_WNDPROC,@ScrollProc()))
  SetProp_(hwnd,@"scrollbar_value",Min)
  ProcedureReturn gid
EndProcedure
Procedure stores the value, because it seems to get called again (twice) on mouse-up, so this only reports on a different value.
Where you see 'Debug \nPos', this is where you do your thing! Works perfect on Win7. Enjoy!
EDIT: Forgot to return the gadget number, fixed.

Re: ScrollBar With Tracking

Posted: Mon Jul 29, 2013 9:49 pm
by minimy
Can you put an example for us, please. Thanks friend!

Re: ScrollBar With Tracking

Posted: Mon Jul 29, 2013 11:46 pm
by CSHW89
@Psych: Great code! Thanks :D

@minimy: Here is a simple example:

Code: Select all

Procedure ScrollProc(SbarID,Msg,wParam,*lParam.SCROLLINFO)
  With *lParam
    Protected result,*defproc=GetProp_(SbarID,@"scrollbar_winproc")
    If *defproc
      result=CallWindowProc_(*defproc,SbarID,Msg,wParam,*lParam)
    EndIf
    If Msg=#SBM_SETSCROLLINFO And *lParam
      If Not \nPos=GetProp_(SbarID,@"scrollbar_value")
        SetProp_(SbarID,@"scrollbar_value",\nPos)
        Debug "Smooth: "+Str(\nPos)
      EndIf
    EndIf
    ProcedureReturn result
  EndWith
EndProcedure
Procedure SmoothScrollBarGadget(Gadget,x,y,Width,Height,Min,Max,PageLength,flags=0)
  Protected hwnd,gid=ScrollBarGadget(Gadget,x,y,Width,Height,Min,Max,PageLength,flags)
  hwnd=gid
  If Gadget=#PB_Any
    hwnd=GadgetID(gid)
  EndIf
  SetProp_(hwnd,@"scrollbar_winproc",SetWindowLongPtr_(hwnd,#GWLP_WNDPROC,@ScrollProc()))
  SetProp_(hwnd,@"scrollbar_value",Min)
  ProcedureReturn gid
EndProcedure


If OpenWindow(0, 0, 0, 305, 140, "ScrollBarGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget       (2,  10, 25, 250,  20, "ScrollBar Standard  (start=50, page=30/100)",#PB_Text_Center)
  ScrollBarGadget  (0,  10, 42, 250,  20, 0, 100, 30)
  SetGadgetState   (0,  50)   ; wir setzen den ersten Schiebebalken (ID = 0) auf 50 von 100
  TextGadget       (3,  10,115, 250,  20, "ScrollBar Vertical  (start=100, page=50/300)",#PB_Text_Right)
  SmoothScrollBarGadget  (1, 270, 10,  25, 120 ,0, 300, 50, #PB_ScrollBar_Vertical)
  SetGadgetState   (1, 100)   ; wir setzen den zweiten Schiebebalken (ID = 1) auf 100 von 300
  Repeat
    event = WaitWindowEvent()
    
    If (event = #PB_Event_Gadget)
      Select EventGadget()
      Case 0
        Debug "NoSmooth: "+Str(GetGadgetState(0))
      EndSelect
    EndIf
    
  Until (event = #PB_Event_CloseWindow)
EndIf
lg Kevin

Re: ScrollBar With Tracking

Posted: Tue Jul 30, 2013 12:41 am
by Fred
And the 5.20 way:

Code: Select all

Procedure ScrollbarEvent()
  Debug "Scroll: "+GetGadgetState(0)
EndProcedure

If OpenWindow(0, 0, 0, 305, 140, "ScrollBarGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget       (2,  10, 25, 250,  20, "ScrollBar Standard  (start=50, page=30/100)",#PB_Text_Center)
  ScrollBarGadget  (0,  10, 42, 250,  20, 0, 100, 30)
  SetGadgetState   (0,  50)   ; wir setzen den ersten Schiebebalken (ID = 0) auf 50 von 100
  BindGadgetEvent(0, @ScrollbarEvent())
  
  Repeat
    event = WaitWindowEvent()
  Until event = #PB_Event_CloseWindow
EndIf

Re: ScrollBar With Tracking

Posted: Tue Jul 30, 2013 2:29 am
by fsw
@Fred,
Not on Linux.
Can't even see the ScrollBar.
Not with GTK2 and GTK3.

Re: ScrollBar With Tracking

Posted: Tue Jul 30, 2013 3:49 am
by StarBootics
fsw wrote:@Fred,
Not on Linux.
Can't even see the ScrollBar.
Not with GTK2 and GTK3.
The GTK 3 subsystem work for you ? Because on Linux Mint 14 x64 with cinnamon as desktop (GTK 3) it didn't work at all. I get a message box about "Linker error" with a very very long list of "Undefined reference to" a lot of gtk key function.

Fred, maybe this should be treated as bug, don't you ?

Regards
StarBootics

Re: ScrollBar With Tracking

Posted: Tue Jul 30, 2013 5:56 am
by fsw
Some stuff works with GTK3... some doesn't.

But in the end it's unusable:
http://purebasic.fr/english/viewtopic.php?f=23&t=55128
http://purebasic.fr/english/viewtopic.php?f=23&t=55587
http://purebasic.fr/english/viewtopic.php?f=23&t=55301
Just to name a few...

Even the PB-Editor is unusable from time to time.
(after using ctrl-c...)

Really hope that Fred is not jumping the gun and releases 5.2 without fixing the editor and gtk3 first.

OS: Manjaro XFCE 64.

Re: ScrollBar With Tracking

Posted: Tue Jul 30, 2013 1:25 pm
by oreopa
Fred wrote:And the 5.20 way:

Code: Select all

Procedure ScrollbarEvent()
  Debug "Scroll: "+GetGadgetState(0)
EndProcedure

If OpenWindow(0, 0, 0, 305, 140, "ScrollBarGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget       (2,  10, 25, 250,  20, "ScrollBar Standard  (start=50, page=30/100)",#PB_Text_Center)
  ScrollBarGadget  (0,  10, 42, 250,  20, 0, 100, 30)
  SetGadgetState   (0,  50)   ; wir setzen den ersten Schiebebalken (ID = 0) auf 50 von 100
  BindGadgetEvent(0, @ScrollbarEvent())
  
  Repeat
    event = WaitWindowEvent()
  Until event = #PB_Event_CloseWindow
EndIf
This bind stuff is very good. :D

Re: ScrollBar With Tracking

Posted: Tue Jul 30, 2013 4:02 pm
by morosh
+1

Re: ScrollBar With Tracking

Posted: Sun Aug 25, 2013 6:50 pm
by minimy
Thank you very much CSHW89!! is very interesting :D

Re: ScrollBar With Tracking

Posted: Tue Sep 24, 2013 3:14 pm
by Lord
Fred wrote:And the 5.20 way:

Code: Select all

Procedure ScrollbarEvent()
  Debug "Scroll: "+GetGadgetState(0)
EndProcedure

If OpenWindow(0, 0, 0, 305, 140, "ScrollBarGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget       (2,  10, 25, 250,  20, "ScrollBar Standard  (start=50, page=30/100)",#PB_Text_Center)
  ScrollBarGadget  (0,  10, 42, 250,  20, 0, 100, 30)
  SetGadgetState   (0,  50)   ; wir setzen den ersten Schiebebalken (ID = 0) auf 50 von 100
  BindGadgetEvent(0, @ScrollbarEvent())
  
  Repeat
    event = WaitWindowEvent()
  Until event = #PB_Event_CloseWindow
EndIf
Why are there two events fired each time I press up or down arrow once?
If up or down arrow pressed continously, its counting smooth up and down by one.

Re: ScrollBar With Tracking

Posted: Tue Sep 24, 2013 4:16 pm
by jassing
Lord wrote:Why are there two events fired each time I press up or down arrow once?
One is fired on mouse-button-down; another on mouse-button-up.

Re: ScrollBar With Tracking

Posted: Tue Sep 24, 2013 7:10 pm
by Lord
jassing wrote:
Lord wrote:Why are there two events fired each time I press up or down arrow once?
One is fired on mouse-button-down; another on mouse-button-up.
Oh, that's bad. TrackBarGadget() doesn't support EventType().
So you can't distinguish between mouse down, up and a repeated
event while holding down mouse button.
Is there a way to do so?

Re: ScrollBar With Tracking

Posted: Tue Sep 24, 2013 8:06 pm
by jassing
the easy way is to use a static var in teh callback -- if the new value is the same as the static one; there has been no change... if they are different, a change has been made, and then update the static var.

Re: ScrollBar With Tracking

Posted: Wed Sep 25, 2013 7:43 am
by Lord
jassing wrote:the easy way is to use a static var in teh callback -- if the new value is the same as the static one; there has been no change... if they are different, a change has been made, and then update the static var.
Thank you for your answer.
So it works like this:

Code: Select all

Procedure ScrollbarEvent()
  Protected Actual
  Static State
  Actual=GetGadgetState(0)
  If Actual<>State
    State=Actual
    Debug "State changed:"
    Debug State
  EndIf
  
EndProcedure

If OpenWindow(0, 0, 0, 305, 140, "ScrollBarGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TextGadget       (2,  10, 25, 250,  20, "ScrollBar Standard  (start=50, page=30/100)",#PB_Text_Center)
  ScrollBarGadget  (0,  10, 42, 250,  20, 0, 100, 30)
  SetGadgetState   (0,  50)   ; wir setzen den ersten Schiebebalken (ID = 0) auf 50 von 100
  BindGadgetEvent(0, @ScrollbarEvent())
 
  Repeat
    event = WaitWindowEvent()
  Until event = #PB_Event_CloseWindow
EndIf