Page 1 of 1

Putting a trackbar in a statusbar

Posted: Thu Oct 29, 2020 4:50 pm
by XCoder
Recently I needed to put a trackbar gadget in a status bar. The purpose of the trackbar gadget was to zoom in on text in an editor gadget. This was not straightforward as I found that when the main window was resized, the trackbar gadget disappeared. I could not find how to do this on the PB forums so I toyed with PB to find a solution.

I am posting my solution here in case anybody else needs to do this.

Code: Select all

EnableExplicit

Enumeration
  #MainWindow
  #StatusBar
  #EditorGadget
  #TrackBarGadget
EndEnumeration

Global StatusRect.RECT, hEdit, hStatus
Global Maxrange, MaxD, sliderValue
Global EventID

Procedure MakeStatusBar()
  Protected hStatus
  hStatus = CreateStatusBar(#StatusBar, WindowID(#MainWindow))
  AddStatusBarField(90)
  AddStatusBarField(100)
  AddStatusBarField(200)
  AddStatusBarField(#PB_Ignore) ; automatically resize this field
  StatusBarText(#StatusBar, 0, "First bar field")
  StatusBarText(#StatusBar, 1, "Second bar field")
  ProcedureReturn hStatus
EndProcedure

Procedure SizeWindowHandler()
  Protected statusHeight
  Shared hStatus
  statusHeight= StatusBarHeight(#StatusBar)
  SendMessage_(hStatus, #SB_GETRECT, 2, StatusRect) ;2 refs the third panel in the statusbar
  ResizeGadget(#TrackBarGadget, #PB_Ignore, WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar)+5, #PB_Ignore, #PB_Ignore)
  ResizeGadget(#EditorGadget, #PB_Ignore, #PB_Ignore, WindowWidth(#MainWindow), WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar))
  FreeStatusBar(#StatusBar) 
  hStatus = MakeStatusBar()
EndProcedure

OpenWindow(#MainWindow, 100, 200, 600, 400, "Gadget on status bar", #PB_Window_MinimizeGadget| #PB_Window_SizeGadget |#PB_Window_SizeGadget)

Maxrange=400 
MaxD=Maxrange/64 +1 
TrackBarGadget(#TrackBarGadget, 197, WindowHeight(#MainWindow)-20, 195, 20, 1, Maxrange )

hStatus = MakeStatusBar()
hEdit=EditorGadget(#EditorGadget,1,0,WindowWidth(#MainWindow), WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar)) 
SetGadgetText(#EditorGadget, "Use the slider to resize the text!") 

BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

Repeat 
  EventID = WaitWindowEvent() 
  If EventID = #PB_Event_Gadget
    Select EventGadget()
        
      Case  #TrackBarGadget 
        sliderValue=GetGadgetState(#TrackBarGadget) 
        If SendMessage_(hEdit,#EM_SETZOOM,sliderValue,MaxD) = #False
          Debug "Error, Cannot set new zooming Range" 
        EndIf
        
    EndSelect
  EndIf 
Until EventID = #PB_Event_CloseWindow 
This solution is not perfect; I discovered that the status bar needs to be created after the TrackBar gadget has been created to make the trackbar gadget stay on top of the status bar. This led me to overcome the problem of the trackbar disappearing when the main window is resized by first resizing the Trackbar gadget then freeing the status bar and then recreating the status bar. This is a clumsy solution. I would be interested to know if anybody can improve on it. I think it is possible to avoid this in VB by making the trackbar control a child of the status window but I could not achieve this in PB.

Re: Putting a trackbar in a statusbar

Posted: Thu Oct 29, 2020 5:11 pm
by infratec
You can use this:
viewtopic.php?f=27&t=72513

Re: Putting a trackbar in a statusbar

Posted: Thu Oct 29, 2020 6:17 pm
by breeze4me
The simpler way is to use SetParent_() API.

Code: Select all

EnableExplicit

Enumeration
  #MainWindow
  #StatusBar
  #EditorGadget
  #TrackBarGadget
EndEnumeration

Global StatusRect.RECT, hEdit, hStatus
Global Maxrange, MaxD, sliderValue
Global EventID

Procedure SizeWindowHandler()
  ResizeGadget(#EditorGadget, #PB_Ignore, #PB_Ignore, WindowWidth(#MainWindow), WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar))
EndProcedure

OpenWindow(#MainWindow, 100, 200, 600, 400, "Gadget on status bar", #PB_Window_MinimizeGadget| #PB_Window_SizeGadget |#PB_Window_SizeGadget)

hStatus = CreateStatusBar(#StatusBar, WindowID(#MainWindow))
AddStatusBarField(90)
AddStatusBarField(100)
AddStatusBarField(200)
AddStatusBarField(#PB_Ignore) ; automatically resize this field
StatusBarText(#StatusBar, 0, "First bar field")
StatusBarText(#StatusBar, 1, "Second bar field")

Maxrange=400 
MaxD=Maxrange/64 +1 

hEdit=EditorGadget(#EditorGadget,1,0,WindowWidth(#MainWindow), WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar)) 
SetGadgetText(#EditorGadget, "Use the slider to resize the text!") 

SendMessage_(hStatus, #SB_GETRECT, 2, StatusRect) ;2 refs the third panel in the statusbar
TrackBarGadget(#TrackBarGadget, StatusRect\left, StatusRect\top, 195, StatusRect\bottom - StatusRect\top * 2, 1, Maxrange )

;for DPI awareness
;TrackBarGadget(#TrackBarGadget, DesktopUnscaledX(StatusRect\left), DesktopUnscaledY(StatusRect\top), DesktopUnscaledX(195), DesktopUnscaledY(StatusRect\bottom - StatusRect\top * 2), 1, Maxrange )

SetParent_(GadgetID(#TrackBarGadget), hStatus)

BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

Repeat 
  EventID = WaitWindowEvent() 
  If EventID = #PB_Event_Gadget
    Select EventGadget()
        
      Case  #TrackBarGadget 
        sliderValue=GetGadgetState(#TrackBarGadget) 
        If SendMessage_(hEdit,#EM_SETZOOM,sliderValue,MaxD) = #False
          Debug "Error, Cannot set new zooming Range" 
        EndIf
        
    EndSelect
  EndIf 
Until EventID = #PB_Event_CloseWindow 

Re: Putting a trackbar in a statusbar

Posted: Thu Oct 29, 2020 6:23 pm
by RASHAD
My 2 cents
Simple as I can

Code: Select all

LoadFont(0,"Arial",12,#PB_Font_Bold | #PB_Font_Italic )

If OpenWindow(0, 0, 0, 600, 400, "PureBasic - StatusBar Example", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)
 
  CreateStatusBar(0, WindowID(0))
  AddStatusBarField(200)
  AddStatusBarField(200)
  AddStatusBarField(#PB_Ignore )
  
  StatusBarText(0,0,"")
  StatusBarText(0,1,"")
  StatusBarText(0,2,"",#PB_StatusBar_Center)
  
  SendMessage_(StatusBarID(0), #SB_SETMINHEIGHT, 30,0)
  SendMessage_(StatusBarID(0), #WM_SIZE, 0,0)
  
  SendMessage_(StatusBarID(0),#SB_GETRECT,0,r.RECT)
  
  ContainerGadget(0,r\left,r\top,r\right-r\left,r\bottom-r\top)
    TextGadget(10,0,0,r\right-r\left,r\bottom-r\top," Test 4 Status",#SS_CENTER|#SS_CENTERIMAGE)
    SetGadgetColor(10,#PB_Gadget_BackColor,$CCFEFC)
    SetGadgetColor(10,#PB_Gadget_FrontColor,$0000FF)
    SetGadgetFont(10,FontID(0))
  CloseGadgetList()  
  SetParent_(GadgetID(0),StatusBarID(0))
  
  SendMessage_(StatusBarID(0),#SB_GETRECT,1,r.RECT)
  TrackBarGadget(1,r\left,r\top,r\right-r\left,r\bottom-r\top,0,100)
  SetParent_(GadgetID(1),StatusBarID(0))
  
  SendMessage_(StatusBarID(0),#SB_GETRECT,2,r.RECT)
  StringGadget(2,r\left,r\top,r\right-r\left,r\bottom-r\top,"TEST")
  SetParent_(GadgetID(2),StatusBarID(0))
  
  Repeat
   
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: Putting a trackbar in a statusbar

Posted: Fri Oct 30, 2020 9:23 am
by dige
Cool stuff! :D Thx

Re: Putting a trackbar in a statusbar

Posted: Fri Oct 30, 2020 10:21 am
by XCoder
Thank you for these alternative solutions.

I see that some of the solutions set the trackbar as a child of the statusbar. I had tried to do this but for some reason it did not work. Unfortunately I did not keep the erroneous code so now I can't see where I was going wrong. Doh! Perhaps I was trying to use SetParent_() in the wrong place in my code.

Re: Putting a trackbar in a statusbar

Posted: Fri Oct 30, 2020 12:51 pm
by RASHAD
Another approach

Code: Select all

LoadFont(0,"Georgia",16,#PB_Font_Bold | #PB_Font_Italic )

If OpenWindow(0, 100, 150, 800, 400, "PureBasic - StatusBar Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered| #PB_Window_SizeGadget)

  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(750 )
  EndIf
  sbHwnd = StatusBarID(0)
  SendMessage_(sbHwnd, #SB_SETMINHEIGHT, 40, 0)
  SendMessage_(sbHwnd, #WM_SIZE, 0,0)
  UseGadgetList(sbHwnd)
  cont = ContainerGadget(#PB_Any,1,1,600,38)
    TextGadget(0,0,0,200,38," Test 4 Status",#WS_BORDER|#SS_NOTIFY | #SS_CENTER|#SS_CENTERIMAGE)
    GadgetToolTip(0," Current Status ")
    SetGadgetColor(0,#PB_Gadget_BackColor,$CCFEFC)
    SetGadgetColor(0,#PB_Gadget_FrontColor,$0000FF)
    SetGadgetFont(0,FontID(0))
    TrackBarGadget(1,200,0,150,38,0,100)    
    StringGadget(2,350,0,200,38,"TEST")
  CloseGadgetList()
  UseGadgetList(WindowID(0))
  ButtonGadget(10,10,10,80,24,"RUN")
Repeat   
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          Debug GetGadgetState(1)
          
        Case 10
          SetGadgetText(0,"New Text")
      EndSelect
        
  EndSelect
Until Quit = 1
  
EndIf 

Re: Putting a trackbar in a statusbar

Posted: Sat Oct 31, 2020 3:58 pm
by XCoder
Thanks, Rashid, for the other approach. This would allow more controls to be added to the statusbar, including a combo box.

I needed to ensure that the trackbar is always on the far right-hand side of the statusbar. I did this by applying the ResizeGadget() function to the trackbar in the procedure SizeWindowHandler() and including a penultimate statusbar field that has the argument #PB_Ignore:

Code: Select all

EnableExplicit

Enumeration
  #MainWindow
  #StatusBar
  #EditorGadget
  #TrackBarGadget
EndEnumeration

#Denominator=4

Global StatusRect.RECT, hEdit, hStatus
Global sliderValue, hTrackBar
Global EventID

Procedure MakeStatusBar()
  Protected hStatus
  hStatus = CreateStatusBar(#StatusBar, WindowID(#MainWindow))
  AddStatusBarField(90)
  StatusBarText(#StatusBar, 0, "First bar field")
  AddStatusBarField(100)
  StatusBarText(#StatusBar, 1, "Second bar field")
  AddStatusBarField(#PB_Ignore) ; automatically resize this field
  AddStatusBarField(200)
  ProcedureReturn hStatus
EndProcedure

Procedure SizeWindowHandler()
  ResizeGadget(#EditorGadget, #PB_Ignore, #PB_Ignore, WindowWidth(#MainWindow), WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar))
  ResizeGadget(#TrackBarGadget, WindowWidth(#MainWindow)-220, #PB_Ignore, #PB_Ignore, #PB_Ignore)
EndProcedure

OpenWindow(#MainWindow, 100, 200, 600, 400, "Gadget on status bar", #PB_Window_MinimizeGadget| #PB_Window_SizeGadget |#PB_Window_SizeGadget)
   
hStatus = MakeStatusBar()
SendMessage_(hStatus, #SB_GETRECT, 3, StatusRect) ; the number 3 refs the 4th statusbar field

hTrackBar = TrackBarGadget(#TrackBarGadget, WindowWidth(#MainWindow)-220, StatusRect\top, StatusRect\right - StatusRect\left-5, StatusRect\bottom - StatusRect\top * 2, 1, 20 )
SendMessage_(hTrackBar, #TBM_SETPOS, #True, 4)
SendMessage_(hTrackBar, #TBM_SETPAGESIZE, 0, 10)
SetParent_(GadgetID(#TrackBarGadget), hStatus)

hEdit=EditorGadget(#EditorGadget,1,0,WindowWidth(#MainWindow), WindowHeight(#MainWindow)-StatusBarHeight(#StatusBar))
SetGadgetText(#EditorGadget, "Use the slider to resize the text!") 


BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())

Repeat 
  EventID = WaitWindowEvent() 
  If EventID = #PB_Event_Gadget
    Select EventGadget()
        
      Case  #TrackBarGadget 
        sliderValue=GetGadgetState(#TrackBarGadget) 
        If SendMessage_(hEdit, #EM_SETZOOM, sliderValue, #Denominator) = #False
          Debug "Error, Cannot set new zooming Range" 
        EndIf
        
    EndSelect
  EndIf 
Until EventID = #PB_Event_CloseWindow