It is currently Fri May 24, 2013 12:32 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Improved ScrollBarGadget
PostPosted: Mon May 23, 2011 10:15 pm 
Offline
Addict
Addict

Joined: Tue May 06, 2003 5:07 pm
Posts: 2258
Location: UK
Hello,

I'd like the "live" ScrollBar position to be returned through WaitWindowEvent. At the moment, the only way to get the live position of the Scrollbar is to use a thread (see link below), although this is not very convenient.

viewtopic.php?f=13&t=46396

On MacOSX, the Purebasic ScrollBarGadget doesn't behave like most scrollbars from other apps, the scrollbar tracker position doesnt change position while dragged (and nor is the scrollbar live position returned) (see link below)

viewtopic.php?f=3&t=45713

freak wrote:
This is a windows specific weirdness. It basically stops sending any messages to the event queue
while the draging of the scrollbar is processed.

The only way to work around this is to write all the mouse handling code for
the scrollbar manually, which would be a nightmare to get right for every windows version.

You'll just have to live with the callback solution on Windows.
For Linux and OSX all this is no problem. The events come in as expected.

viewtopic.php?f=5&t=31141

I don't know about Linux, but on OSX (last version) the event does not come as expected: the scrollbar fire an event on mouseup only.


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Tue May 24, 2011 8:42 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
Polo wrote:
On MacOSX, the Purebasic ScrollBarGadget doesn't behave like most scrollbars from other apps, the scrollbar tracker position doesnt change position while dragged (and nor is the scrollbar live position returned) (see link below)

http://forums.purebasic.com/english/vie ... =3&t=45713

This is a MacOS X workaround with a ScrollBar created with an API call which provides
true live tracking. Unfortunately I didn't find any way to enable live tracking in a PB
ScrollBarGadget because this feature can only to be enabled when creating this control.
So I endorse Niffo's proposal to enable live tracking when creating the ScrollBarGadget
in PB internally.
Code:
ImportC ""
  CreateScrollBarControl(WindowRef.L, *BoundsRect, CurrentValue.L, MinimumValue.L, MaximumValue.L, ViewSize.L, LiveTracking.L, LiveTrackingProc.L, *ControlRef)
  GetControl32BitMaximum(ControlRef.L)
  GetControl32BitMinimum(ControlRef.L)
  GetControl32BitValue(ControlRef.L)
  SetControl32BitValue(ControlRef.L, NewValue.L)
  ShowControl(ControlRef.L)
EndImport

#kControlDownButtonPart = 21
#kControlUpButtonPart = 20

Structure Rect
  Top.W
  Left.W
  Bottom.W
  Right.W
EndStructure

ProcedureCDLL LiveTrackingProc(ControlRef.L, PartCode.L)
  Shared ScrollBarRef.L

  Protected CurrentPosition.L

  If ControlRef = ScrollBarRef
    Select PartCode
      Case #kControlUpButtonPart
        CurrentPosition = GetControl32BitValue(ControlRef)

        If CurrentPosition > GetControl32BitMinimum(ControlRef)
          SetControl32BitValue(ControlRef.L, CurrentPosition - 1)
        EndIf
      Case #kControlDownButtonPart
        CurrentPosition = GetControl32BitValue(ControlRef)

        If CurrentPosition < GetControl32BitMaximum(ControlRef)
          SetControl32BitValue(ControlRef.L, CurrentPosition + 1)
        EndIf
    EndSelect

    SetGadgetText(3, Str(GetControl32BitValue(ControlRef)))
  EndIf
EndProcedure

Define Bounds.Rect

Bounds\Left   = 10
Bounds\Top    = 51
Bounds\Right  = 190
Bounds\Bottom = 70

OpenWindow(0, 200, 100, 510, 90, "ScrollBar with Live Tracking")
ScrollBarGadget(0, 10, 20, 180, 20, 0, 120, 20)
SetGadgetState(0, 50)
TextGadget(1, 200, 19, 40, 17, "50", #PB_Text_Border | #PB_Text_Center)
TextGadget(2, 250, 20, 300, 20, "PB ScrollBarGadget with 'Ghost Thumb'")
TextGadget(3, 200, 50, 40, 17, "50", #PB_Text_Border | #PB_Text_Center)
TextGadget(4, 250, 50, 300, 20, "API ScrollBar with 'Live Tracking'")

If CreateScrollBarControl(WindowID(0), @Bounds, 50, 0, 100, 20, #True, @LiveTrackingProc(), @ScrollBarRef) = 0
  ShowControl(ScrollBarRef)

  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #PB_Event_Gadget
        If EventGadget() = 0
          SetGadgetText(1, Str(GetGadgetState(0)))
        EndIf
    EndSelect
  ForEver
EndIf


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Wed May 25, 2011 9:33 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
Polo wrote:
At the moment, the only way to get the live position of the Scrollbar is to use a thread (see link below), although this is not very convenient.

http://forums.purebasic.com/english/vie ... 13&t=46396

You don't need to use a thread to get the live position of the ScrollBar. In Windows
you can utilize a window callback or subclass the ScrollBarGadget. And in Linux
and MacOS X it isn't too difficult neither. Take a look into this cross-platform
example of using a ScrollBar with live scrolling to scroll an image. I have tested it
with PB 4.51 in Windows 98 SE, Windows XP SP2 + SP3, Windows 7 x86 and x64,
andLinux/Kubuntu 9.04 and MacOS X 10.6.7 (Snow Leopard):
Code:
EnableExplicit

Define ScrollStep.F

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    ProcedureC ScrollBarCallback(*Range.GtkRange, ScrollType.L, NewValue.D, UserData.L)
      Shared ScrollStep.F

      GrabImage(0, 1, Int(GetGadgetState(1) * ScrollStep), 0, GadgetWidth(0) - 4, ImageHeight(0))
      SetGadgetState(0, ImageID(1))
    EndProcedure
  CompilerCase #PB_OS_MacOS
    ImportC ""
      CreateScrollBarControl(WindowRef.L, *BoundsRect, CurrentValue.L, MinimumValue.L, MaximumValue.L, ViewSize.L, LiveTracking.L, LiveTrackingProc.L, *ControlRef)
      GetControl32BitMaximum(ControlRef.L)
      GetControl32BitMinimum(ControlRef.L)
      GetControl32BitValue(ControlRef.L)
      SetControl32BitValue(ControlRef.L, NewValue.L)
      ShowControl(ControlRef.L)
    EndImport

    #kControlDownButtonPart = 21
    #kControlUpButtonPart = 20

    Structure Rect
      Top.W
      Left.W
      Bottom.W
      Right.W
    EndStructure

    ProcedureC ScrollBarCallback(ControlRef.L, PartCode.L)
      Shared ScrollStep.F
      Protected CurrentPosition.L
     
      Select PartCode
        Case #kControlUpButtonPart
          CurrentPosition = GetControl32BitValue(ControlRef)
         
          If CurrentPosition > GetControl32BitMinimum(ControlRef)
            SetControl32BitValue(ControlRef.L, CurrentPosition - Int(ScrollStep))
          EndIf
        Case #kControlDownButtonPart
          CurrentPosition = GetControl32BitValue(ControlRef)
         
          If CurrentPosition < GetControl32BitMaximum(ControlRef)
            SetControl32BitValue(ControlRef.L, CurrentPosition + Int(ScrollStep))
          EndIf
      EndSelect
       
      GrabImage(0, 1, Int(GetControl32BitValue(ControlRef) * ScrollStep), 0, GadgetWidth(0) - 4, ImageHeight(0))
      SetGadgetState(0, ImageID(1))
    EndProcedure
  CompilerCase #PB_OS_Windows
    Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
      Shared ScrollStep.F

      If LParam = GadgetID(1)
        If Msg = #WM_HSCROLL
          GrabImage(0, 1, Int(GetGadgetState(1) * ScrollStep), 0, GadgetWidth(0) - 4, ImageHeight(0))
          SetGadgetState(0, ImageID(1))
        EndIf
      EndIf

      ProcedureReturn #PB_ProcessPureBasicEvents
    EndProcedure
CompilerEndSelect

If LoadImage(0, #PB_Compiler_Home + "/examples/sources/Data/PureBasicLogo.bmp")
  OpenWindow(0, 200, 100, 172, 100, "Live tracking", #PB_Window_SystemMenu)
  ImageGadget(0, 5, 5, WindowWidth(0) - 9, ImageHeight(0), 0, #PB_Image_Border)

  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    Define Bounds.Rect
    Define ScrollBarRef.L
   
    Bounds\Left   = 5
    Bounds\Top    = WindowHeight(0) - 20
    Bounds\Right  = WindowWidth(0) - 5
    Bounds\Bottom = WindowHeight(0) - 5

    If CreateScrollBarControl(WindowID(0), @Bounds, 0, 0, GadgetWidth(0), GadgetWidth(0), #True, @ScrollBarCallback(), @ScrollBarRef) = 0
      ShowControl(ScrollBarRef)
      GrabImage(0, 1, GetControl32BitValue(ScrollBarRef), 0, GadgetWidth(0) - 4, ImageHeight(0))
      ScrollStep = (ImageWidth(0) - GadgetWidth(0)) / GadgetWidth(0)
    EndIf
  CompilerElse
    Define ViewSize.I

    ScrollStep = ImageWidth(0) / GadgetWidth(0)
    ViewSize = Int(0.0 + GadgetWidth(0) / ImageWidth(0) * GadgetWidth(0))
    ScrollBarGadget(1, 5, WindowHeight(0) - 20, WindowWidth(0) - 10, 15, 0, GadgetWidth(0), ViewSize)
    GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
  CompilerEndIf

  SetGadgetState(0, ImageID(1))

  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      g_signal_connect_data_(GadgetID(1), "change-value", @ScrollBarCallback(), 0, 0, 0)
    CompilerCase #PB_OS_Windows
      SetWindowCallback(@WindowCallback(), 0)
  CompilerEndSelect
 
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Wed May 25, 2011 9:46 pm 
Offline
Addict
Addict

Joined: Tue May 06, 2003 5:07 pm
Posts: 2258
Location: UK
looks very nice indeed mate, cool to see some cross platform code!

Wish this will be implemented natively in PB though, as this code might not work in the future (i.e. if Purebasic switch to Cocoa :))

Thanks, I'm going to use that! :)


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Thu Jun 09, 2011 2:34 pm 
Offline
Addict
Addict

Joined: Tue May 06, 2003 5:07 pm
Posts: 2258
Location: UK
Hello!

I'm wondering where i can find an API reference for Carbon, i'm struggling to find anything on google...

I'd like to detect in the callback if the user pressed on the up, right, top or bottom arrow of the scrollbar (depending if it's a horizontal or vertical scrollbar), but i'm not sure on how to do this?

Any ideas?

Thanks
Gaetan


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Thu Jun 09, 2011 8:13 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
Polo wrote:
I'm wondering where i can find an API reference for Carbon, i'm struggling to find anything on google...

Control Manager Reference (PDF)

Polo wrote:
I'd like to detect in the callback if the user pressed on the up, right, top or bottom arrow of the scrollbar (depending if it's a horizontal or vertical scrollbar), but i'm not sure on how to do this?

Didn't you try the Mac example of my first posting in this thread? The
Callback LiveTrackingProc() checks the PartCode (the part of the control
which was clicked on) for #kControlUpButtonPart (up arrow in ScrollBar)
and #kControlDownButtonPart (Down arrow in ScrollBar). In a vertical
ScrollBar #kControlUpButtonPart is set on a click onto the left button and
#kControlDownButtonPart for a click onto the right button. You are able
to discriminate between different ScrollBars in the callback by comparing
the parameter ControlRef with the Reference of your different ScrollBar
controls... :wink:

There are no part codes for "Top" and "Bottom" because there are simply
no control elements in the ScrollBar to position the slider to the top or
bottom position at once. I presume that you think of the possibility to
click into an area below or above a slider to move a page up or down.
This is still not implemented in my above example but the PartCodes
constants are:
Code:
#kControlPageUpPart = 22
#kControlPageDownPart = 23


Last edited by Shardik on Thu Jun 09, 2011 8:35 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Thu Jun 09, 2011 8:25 pm 
Offline
Addict
Addict

Joined: Tue May 06, 2003 5:07 pm
Posts: 2258
Location: UK
Can't believe I didn't realise that..!!! Sorry sorry!! :oops:
Thanks again !! :)


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Sat Jun 18, 2011 2:28 am 
Offline
Addict
Addict

Joined: Tue May 06, 2003 5:07 pm
Posts: 2258
Location: UK
Hi,

I've worked on your code Shardik and it's great. I added the page up and down quite easily.

However, I need to get a notification when the main scrollbar button dragging is finished.
With #kControlIndicatorPart = 129 I receive an event in the callback each time the position is moved, while i'd rather have the event when it has finished moving, thus on the mouse up.

Any idea on how to do this? I've seen some code to report mouse events on gadgets, though I'm not sure this is the way to go as it'd be handy to do everything in the same callback :)
Thanks again!
Gaetan


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Mon Jun 27, 2011 8:45 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
Polo wrote:
However, I need to get a notification when the main scrollbar button dragging is finished.
With #kControlIndicatorPart = 129 I receive an event in the callback each time the position is moved, while i'd rather have the event when it has finished moving, thus on the mouse up.

Any idea on how to do this? I've seen some code to report mouse events on gadgets, though I'm not sure this is the way to go as it'd be handy to do everything in the same callback :)

Code:
EnableExplicit

ImportC ""
  CreateScrollBarControl(WindowRef.L, *BoundsRect, CurrentValue.L, MinimumValue.L, MaximumValue.L, ScrollBarViewSize.L, LiveTracking.L, LiveTrackingProc.L, *ControlRef)
  GetControl32BitValue(ControlRef.L)
  SetControl32BitValue(ControlRef.L, NewValue.L)
  ShowControl(ControlRef.L)
  TrackMouseLocation(GrafPortPtr.L, *MouseLocation, *TrackingEvent)
EndImport

#ScrollBarMaximum = 100
#ScrollBarMinimum = 0
#ScrollBarViewSize = 20
#ScrollBarWidth = 170
#ScrollBarX = 20

#kControlDownButtonPart = 21
#kControlIndicatorPart = 129
#kControlPageUpPart = 22
#kControlPageDownPart = 23
#kControlUpButtonPart = 20
#kMouseTrackingMouseUp = 2

Structure Rect
  Top.W
  Left.W
  Bottom.W
  Right.W
EndStructure

ProcedureC LiveTrackingCallback(ScrollBarRef.L, PartCode.L)
  Protected MousePosition.L
  Protected SliderPosition.L
  Protected TrackingEvent.L
  Protected MouseX.L

  Select PartCode
    Case #kControlIndicatorPart
      While TrackingEvent <> #kMouseTrackingMouseUp
        TrackMouseLocation(0, @MousePosition, @TrackingEvent)
        MouseX = MousePosition >> 16
        SliderPosition = Int((MouseX + 0.0) / (#ScrollBarWidth - 64) * (#ScrollBarMaximum - #ScrollBarMinimum)) - 36

        If SliderPosition < #ScrollBarMinimum
          SliderPosition = #ScrollBarMinimum
        EndIf
       
        If SliderPosition > #ScrollBarMaximum
          SliderPosition = #ScrollBarMaximum
        EndIf
       
        SetControl32BitValue(ScrollBarRef, SliderPosition)
        SetGadgetText(1, Str(SliderPosition))
      Wend
     
      Debug "Scroll button was released"
    Case #kControlUpButtonPart
      SliderPosition = GetControl32BitValue(ScrollBarRef)
     
      If SliderPosition > #ScrollBarMinimum
        SetControl32BitValue(ScrollBarRef, SliderPosition - 1)
      EndIf
    Case #kControlDownButtonPart
      SliderPosition = GetControl32BitValue(ScrollBarRef)
     
      If SliderPosition < #ScrollBarMaximum
        SetControl32BitValue(ScrollBarRef, SliderPosition + 1)
      EndIf
    Case #kControlPageUpPart
      SliderPosition = GetControl32BitValue(ScrollBarRef)
     
      If SliderPosition - #ScrollBarViewSize >= #ScrollBarMinimum
        SetControl32BitValue(ScrollBarRef.L, SliderPosition - #ScrollBarViewSize)
      Else
        SetControl32BitValue(ScrollBarRef.L, #ScrollBarMinimum)
      EndIf       
    Case #kControlPageDownPart
      SliderPosition = GetControl32BitValue(ScrollBarRef)
     
      If SliderPosition + #ScrollBarViewSize <= #ScrollBarMaximum
        SetControl32BitValue(ScrollBarRef, SliderPosition + #ScrollBarViewSize)
      Else
        SetControl32BitValue(ScrollBarRef, #ScrollBarMaximum)
      EndIf
  EndSelect
 
  SetGadgetText(1, Str(GetControl32BitValue(ScrollBarRef)))
EndProcedure

Define Bounds.Rect
Define ScrollBarRef.L

Bounds\Left   = #ScrollBarX
Bounds\Top    = 21
Bounds\Right  = #ScrollBarX + #ScrollBarWidth
Bounds\Bottom = 70

OpenWindow(0, 200, 100, 510, 60, "ScrollBar with Live Tracking")
TextGadget(1, 200, 20, 40, 17, "50", #PB_Text_Border | #PB_Text_Center)
TextGadget(2, 250, 20, 300, 20, "API ScrollBar with 'Live Tracking'")

If CreateScrollBarControl(WindowID(0), @Bounds, (#ScrollBarMaximum - #ScrollBarMinimum) / 2, #ScrollBarMinimum, #ScrollBarMaximum, 20, #True, @LiveTrackingCallback(), @ScrollBarRef) = 0
  ShowControl(ScrollBarRef)

  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Wed Jun 29, 2011 2:01 am 
Offline
Addict
Addict

Joined: Tue May 06, 2003 5:07 pm
Posts: 2258
Location: UK
Amazing, cheers mate you're the best! :)


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Fri Aug 05, 2011 3:06 am 
Offline
Addict
Addict
User avatar

Joined: Thu Aug 07, 2003 7:01 pm
Posts: 2853
Location: United Kingdom
It would be great if live tracking of the scrollbars was native to PureBasic in the final 4.60...

Live scrollbars make canvas gadgets much more flexible - you can make custom tree systems, grids, text editors, etc..

_________________
http://www.SinisterSoft.com <- My Business website
http://www.ReportComplete.com and http://www.ReportPlus.co.uk <- School end of term reports system


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Mon Dec 26, 2011 1:43 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Sep 23, 2008 11:38 pm
Posts: 702
Location: Belgium (& Luxembourg)
@Shardik
I have reviewed your code completely, analyzed it from top to bottom because it got my greatest attention. :) But only the Windows part, because I cannot test the other platforms.
ScrollStep is not necessary! Because it is always 1. This is because the logic was not very correct.
I also added the vertical scrollbar for completeness.
Code:
;(c) Shardik 2011-05-25
;(c) Charvista 2011-12-26

EnableExplicit

Enumeration
    #Image     ; loaded image
    #ImageBis  ; duplicate image
    #Gadget    ; image gadget
    #Window    ; window
    #ScbGadH   ; scrollbar gadget horizontal
    #ScbGadV   ; scrollbar gadget vertical
EndEnumeration

Define.i WinWidth,WinHeight,HMarge,VMarge,GWidth,GHeight

Procedure WindowCallback(WindowHandle.i,Msg.i,wParam.i,lParam.i)
    Shared GWidth,GHeight
    If lParam=GadgetID(#ScbGadH) Or lParam=GadgetID(#ScbGadV)
        ;If Msg=#WM_HSCROLL; with this, it will only update if the cursor is ON the scrollbar
                           ; if used here and scrollbar is moved to start or end too quickly, will show some "latency" when the mouse button is released
            GrabImage(#Image,#ImageBis,GetGadgetState(#ScbGadH),GetGadgetState(#ScbGadV),GWidth,GHeight)
            SetGadgetState(#Gadget,ImageID(#ImageBis))
        ;EndIf
    EndIf
    ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

UsePNGImageDecoder()
LoadImage(#Image,#PB_Compiler_Home+"/examples/3D/Data/Water/Foam.png")
WinWidth=200
WinHeight=200
OpenWindow(#Window,0,0,WinWidth,WinHeight,"Image scrolling",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
HMarge=5
VMarge=5
GWidth=WinWidth-(2*HMarge)-20; marge left & right
GHeight=WinHeight-(2*VMarge)-20; marge top & bottom
ImageGadget(#Gadget,HMarge,VMarge,GWidth,ImageHeight(#Image),0,#PB_Image_Border)
; never use ImageWidth() as width for ImageGadget() because this will automatically replace the width of the ImageGadget() with the width of the image!
; so if you want a fixed ImageGadget width, use a fixed value => here GWidth used.
; same rule applies for ImageHeight().

ScrollBarGadget(#ScbGadH,HMarge,WindowHeight(#Window)-20,GWidth,15,0,ImageWidth(#Image),GWidth)
ScrollBarGadget(#ScbGadV,WindowWidth(#Window)-20,VMarge,15,GHeight,0,ImageHeight(#Image),GHeight,#PB_ScrollBar_Vertical)
GrabImage(#Image,#ImageBis,0,0,GWidth,GHeight)
SetGadgetState(#Gadget,ImageID(#ImageBis))
SetWindowCallback(@WindowCallback(),#Window)

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow

_________________
- Future conversation forecasting not yet implemented.
- If the future had copied a program from now, they would have called it version -1.


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Tue Dec 27, 2011 2:18 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
charvista,

thank you for reviewing and expanding my example code.

charvista wrote:
ScrollStep is not necessary! Because it is always 1. This is because the logic was not very correct.
You are right! Although ScrollStep is only 1 if the width/height ratio is 1. In my
example ScrollStep is 2.33742332458496 :wink:
My example isn't wrong but it makes things more difficult as they are. The problem arose
because I used GadgetWidth(0) instead of ImageWidth(0) in the definition of my
ScrollBarGadget... :twisted:

One hint to improve your example: you commented out the test on #WM_HSCROLL in your
WindowCallback. This generates a lot of unneccessary CPU load because on every message
from your ScrollBarGadgets the image will be redrawn. But you are right that my solution is
not very clean because when positioning the scrollbar knob at the beginning or end the image
will be moved a bit when releasing the knob. For a solution you only need to take a look into
the code example from Windows API guru srod: he only updates the image position if the
scrollcode doesn't indicate #SB_THUMBPOSITION or #SB_ENDSCROLL. Therefore I have updated
my Windows example:
Code:
EnableExplicit

Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
  Protected ScrollCode.L
 
  If LParam = GadgetID(1)
    If Msg = #WM_HSCROLL
      ScrollCode = WParam & $FFFF

      If ScrollCode <> #SB_THUMBPOSITION And ScrollCode <> #SB_ENDSCROLL
        GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
        SetGadgetState(0, ImageID(1))
      EndIf
    EndIf
  EndIf
 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If LoadImage(0, #PB_Compiler_Home + "/examples/sources/Data/PureBasicLogo.bmp")
  OpenWindow(0, 200, 100, 172, 100, "Live tracking", #PB_Window_SystemMenu)
  ImageGadget(0, 5, 5, WindowWidth(0) - 9, ImageHeight(0), 0, #PB_Image_Border)
  ScrollBarGadget(1, 5, WindowHeight(0) - 20, WindowWidth(0) - 10, 15, 0, ImageWidth(0), WindowWidth(0) - 10)
  GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
  SetGadgetState(0, ImageID(1))
  SetWindowCallback(@WindowCallback(), 0)

  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


And this is the updated cross-platform example:
Code:
EnableExplicit

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    ProcedureC ScrollBarCallback(*Range.GtkRange, ScrollType.L, NewValue.D, UserData.L)
      GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
      SetGadgetState(0, ImageID(1))
    EndProcedure
  CompilerCase #PB_OS_MacOS
    ImportC ""
      CreateScrollBarControl(WindowRef.L, *BoundsRect, CurrentValue.L, MinimumValue.L, MaximumValue.L, ViewSize.L, LiveTracking.L, LiveTrackingProc.L, *ControlRef)
      GetControl32BitMaximum(ControlRef.L)
      GetControl32BitMinimum(ControlRef.L)
      GetControl32BitValue(ControlRef.L)
      SetControl32BitValue(ControlRef.L, NewValue.L)
      ShowControl(ControlRef.L)
    EndImport

    #kControlDownButtonPart = 21
    #kControlUpButtonPart = 20

    Structure Rect
      Top.W
      Left.W
      Bottom.W
      Right.W
    EndStructure

    ProcedureC ScrollBarCallback(ControlRef.L, PartCode.L)
      Protected CurrentPosition.L
     
      Select PartCode
        Case #kControlUpButtonPart
          CurrentPosition = GetControl32BitValue(ControlRef)
         
          If CurrentPosition > GetControl32BitMinimum(ControlRef)
            SetControl32BitValue(ControlRef.L, CurrentPosition)
          EndIf
        Case #kControlDownButtonPart
          CurrentPosition = GetControl32BitValue(ControlRef)
         
          If CurrentPosition < GetControl32BitMaximum(ControlRef)
            SetControl32BitValue(ControlRef.L, CurrentPosition)
          EndIf
      EndSelect
       
      GrabImage(0, 1, GetControl32BitValue(ControlRef), 0, GadgetWidth(0) - 4, ImageHeight(0))
      SetGadgetState(0, ImageID(1))
    EndProcedure
  CompilerCase #PB_OS_Windows
    Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
      Protected ScrollCode.L

      If LParam = GadgetID(1)
        If Msg = #WM_HSCROLL
          ScrollCode = WParam & $FFFF

          If ScrollCode <> #SB_THUMBPOSITION And ScrollCode <> #SB_ENDSCROLL
            GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
            SetGadgetState(0, ImageID(1))
          EndIf
        EndIf
      EndIf

      ProcedureReturn #PB_ProcessPureBasicEvents
    EndProcedure
CompilerEndSelect

If LoadImage(0, #PB_Compiler_Home + "/examples/sources/Data/PureBasicLogo.bmp")
  OpenWindow(0, 200, 100, 172, 100, "Live tracking", #PB_Window_SystemMenu)
  ImageGadget(0, 5, 5, WindowWidth(0) - 9, ImageHeight(0), 0, #PB_Image_Border)

  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    Define Bounds.Rect
    Define ScrollBarRef.L
   
    Bounds\Left   = 5
    Bounds\Top    = WindowHeight(0) - 20
    Bounds\Right  = WindowWidth(0) - 5
    Bounds\Bottom = WindowHeight(0) - 5

    If CreateScrollBarControl(WindowID(0), @Bounds, 0, 0, GadgetWidth(0), GadgetWidth(0), #True, @ScrollBarCallback(), @ScrollBarRef) = 0
      ShowControl(ScrollBarRef)
      GrabImage(0, 1, GetControl32BitValue(ScrollBarRef), 0, GadgetWidth(0) - 4, ImageHeight(0))
    EndIf
  CompilerElse
    ScrollBarGadget(1, 5, WindowHeight(0) - 20, WindowWidth(0) - 10, 15, 0, ImageWidth(0), WindowWidth(0) - 10)
    GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
  CompilerEndIf

  SetGadgetState(0, ImageID(1))

  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      g_signal_connect_data_(GadgetID(1), "change-value", @ScrollBarCallback(), 0, 0, 0)
    CompilerCase #PB_OS_Windows
      SetWindowCallback(@WindowCallback(), 0)
  CompilerEndSelect
 
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Tue Dec 27, 2011 5:09 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Sep 23, 2008 11:38 pm
Posts: 702
Location: Belgium (& Luxembourg)
Shardik,
It was a real pleasure to look at your code :)
Your code is much better now :D And true, adding Srod's code for your ScrollCode is good to put a halt to CPU consuming, but there is still a practical problem. For the eyes, your updated code is much nicer as it no longer moves a bit when releasing the knob, but... the image is not at position 0 as the user should expect when doing that rapid movement: you still need to click several times on the small arrow of the scrollbar to go to the real start or end of the image. I still need to do more tests to see how to solve your problem while maintaining #WM_HSCROLL (or #WM_VSCROLL)...
As a side question: does it really consume so much CPU? How can I verify that? The Windows Task Manager does not show exceptional CPU changes... besides, it occurs only when the user has the mouse clicked on the scrollbar, so it is temporary... (and we don't expect the user keeping his finger down on that scrollbar for hours, do we? Yes, this can occur when thinking about the image while scrolling slowly, but then scrolling occurs effectively). Otherwise, adding Delay(10) in the WindowCallback() can already slow down CPU usage, without feeling erratic image movements.

_________________
- Future conversation forecasting not yet implemented.
- If the future had copied a program from now, they would have called it version -1.


Top
 Profile  
 
 Post subject: Re: Improved ScrollBarGadget
PostPosted: Wed Dec 28, 2011 3:04 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
charvista wrote:
As a side question: does it really consume so much CPU? How can I verify that?

You can indirectly prove that by establishing 3 counters in the WindowCallback
and counting how many redraws would have been done with and without
filtering events. And you should also take into account that scrolling a small
image might be negligible but scrolling a large image should produce an
annoying flicker if you redraw the image on every occasion... :wink:
Code:
EnableExplicit

Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
  Static MsgCount1.I
  Static MsgCount2.I
  Static MsgCount3.I
  Protected ScrollCode.L
 
  If LParam = GadgetID(1)
    MsgCount1 + 1

    If Msg = #WM_HSCROLL
      MsgCount2 + 1
      ScrollCode = WParam & $FFFF

      If ScrollCode <> #SB_THUMBPOSITION And ScrollCode <> #SB_ENDSCROLL
        MsgCount3 + 1
        GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
        SetGadgetState(0, ImageID(1))

        Debug "Redraws for messages generated by ScrollBarGadget: " + Str(MsgCount1)
        Debug "Redraws with filtering of #WM_HSCROLL: " + Str(MsgCount2)
        Debug "Redraws with filtering of #WM_HSCROLL and ScrollCode: " + Str(MsgCount3)
      EndIf
    EndIf
  EndIf
 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If LoadImage(0, #PB_Compiler_Home + "/examples/sources/Data/PureBasicLogo.bmp")
  OpenWindow(0, 200, 100, 172, 100, "Live tracking", #PB_Window_SystemMenu)
  ImageGadget(0, 5, 5, WindowWidth(0) - 9, ImageHeight(0), 0, #PB_Image_Border)
  ScrollBarGadget(1, 5, WindowHeight(0) - 20, WindowWidth(0) - 10, 15, 0, ImageWidth(0), WindowWidth(0) - 10)
  GrabImage(0, 1, GetGadgetState(1), 0, GadgetWidth(0) - 4, ImageHeight(0))
  SetGadgetState(0, ImageID(1))
  SetWindowCallback(@WindowCallback(), 0)

  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Try to move the scroll knob several times and you will see a lot of unneccessary redraws
without event filtering... :wink:


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye