ScrollBar With Tracking

Share your advanced PureBasic knowledge/code with the community.
Psych
Enthusiast
Enthusiast
Posts: 239
Joined: Thu Dec 18, 2008 3:35 pm
Location: Wales, UK

ScrollBar With Tracking

Post 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.
----------------------------------------------------------------------------
Commenting your own code is admitting you don't understand it.
----------------------------------------------------------------------------
User avatar
minimy
Enthusiast
Enthusiast
Posts: 552
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: ScrollBar With Tracking

Post by minimy »

Can you put an example for us, please. Thanks friend!
If translation=Error: reply="Sorry, Im Spanish": Endif
CSHW89
User
User
Posts: 30
Joined: Thu Sep 09, 2010 2:47 pm

Re: ScrollBar With Tracking

Post 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
Image Image Image
Fred
Administrator
Administrator
Posts: 18154
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: ScrollBar With Tracking

Post 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
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: ScrollBar With Tracking

Post by fsw »

@Fred,
Not on Linux.
Can't even see the ScrollBar.
Not with GTK2 and GTK3.

I am to provide the public with beneficial shocks.
Alfred Hitshock
User avatar
StarBootics
Addict
Addict
Posts: 1006
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Re: ScrollBar With Tracking

Post 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
The Stone Age did not end due to a shortage of stones !
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: ScrollBar With Tracking

Post 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.

I am to provide the public with beneficial shocks.
Alfred Hitshock
User avatar
oreopa
Enthusiast
Enthusiast
Posts: 283
Joined: Sat Jun 24, 2006 3:29 am
Location: Edinburgh, Scotland.

Re: ScrollBar With Tracking

Post 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
Proud supporter of PB! * Musician * C64/6502 Freak
morosh
Enthusiast
Enthusiast
Posts: 329
Joined: Wed Aug 03, 2011 4:52 am
Location: Beirut, Lebanon

Re: ScrollBar With Tracking

Post by morosh »

+1
PureBasic: Surprisingly simple, diabolically powerful
User avatar
minimy
Enthusiast
Enthusiast
Posts: 552
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: ScrollBar With Tracking

Post by minimy »

Thank you very much CSHW89!! is very interesting :D
If translation=Error: reply="Sorry, Im Spanish": Endif
User avatar
Lord
Addict
Addict
Posts: 900
Joined: Tue May 26, 2009 2:11 pm

Re: ScrollBar With Tracking

Post 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.
Image
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: ScrollBar With Tracking

Post 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.
User avatar
Lord
Addict
Addict
Posts: 900
Joined: Tue May 26, 2009 2:11 pm

Re: ScrollBar With Tracking

Post 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?
Image
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: ScrollBar With Tracking

Post 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.
User avatar
Lord
Addict
Addict
Posts: 900
Joined: Tue May 26, 2009 2:11 pm

Re: ScrollBar With Tracking

Post 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
Image
Post Reply