Synchronised Scroll Bars Swimming
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Synchronised Scroll Bars Swimming
Ok, it's not about swimming. It's about List Icon Gadgets or List View Gadgets - If you have a pair side-by-side, how can you synchronise them such that when you move the scroll bar on one, the scroll bar on the other moves with it?
Last edited by IdeasVacuum on Mon Aug 12, 2013 1:54 pm, edited 2 times in total.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Sychronised Swimming
Hi IdeasVacuum
Next snippet By FB (Fluid Byte)
And if you search the forum you will find a complicated one By Me to fix the first column too
Next snippet By FB (Fluid Byte)
And if you search the forum you will find a complicated one By Me to fix the first column too
Code: Select all
OpenWindow(0,0,0,415,320,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ContainerGadget(0,5,5,200 - 2 - 17,310)
ListIconGadget(1,0,0,200,310,"Name",170)
CloseGadgetList()
ListIconGadget(2,190,5,200,310,"Name",170)
For i=1 To 500
AddGadgetItem(1,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
AddGadgetItem(2,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
Next
Structure NMLVSCROLL
hdr.NMHDR
dx.l
dy.l
EndStructure
Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
Select uMsg
Case #WM_NOTIFY
Protected *pnmh.NMHDR = lParam
If *pnmh\hwndFrom = GadgetID(2)
If *pnmh\code = #LVN_ENDSCROLL
Protected *pnms.NMLVSCROLL = lParam
Protected LVTI = SendMessage_(GadgetID(2),#LVM_GETTOPINDEX,0,0)
Protected LVCP = SendMessage_(GadgetID(2),#LVM_GETCOUNTPERPAGE,0,0)
If *pnms\dy < 0
SendMessage_(GadgetID(1),#LVM_ENSUREVISIBLE,LVTI,0)
ElseIf *pnms\dy > 0
SendMessage_(GadgetID(1),#LVM_ENSUREVISIBLE,LVTI + LVCP - 1,0)
EndIf
EndIf
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
SetWindowCallback(@WindowCallback())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Egypt my love
Re: Sychronised Swimming
With 2 ListViewGadget:
1 ListViewGadget and 1 ListIconGadget, synchronized Top Index:
Code: Select all
Procedure MouseOverGadget(window,gadget)
If (WindowMouseX(window) >= GadgetX(gadget)) And (WindowMouseX(window) <= (GadgetX(gadget)+GadgetWidth(gadget)))
If (WindowMouseY(window) >= GadgetY(gadget)) And (WindowMouseY(window) <= (GadgetY(gadget)+GadgetHeight(gadget)))
ProcedureReturn #True
EndIf
EndIf
EndProcedure
Procedure Syncro(hWnd,msg,wParam,lParam)
Static activeGadgetID=0
gadget = GetWindowLongPtr_(hWnd,#GWL_ID)
If msg = #WM_VSCROLL
If gadget = 0 Or gadget = 1 ; both ListView
If MouseOverGadget(0,gadget)
activeGadgetID=hWnd
EndIf
If activeGadgetID=hWnd
If gadget = 0 : target = 1
Else : target = 0
EndIf
;pos = GetScrollPos_(hWnd,#SB_VERT)
;SetScrollPos_(GadgetID(target),#SB_VERT,pos,1)
top = SendMessage_( hWnd ,#LB_GETTOPINDEX ,0,0)
SendMessage_(GadgetID(target),#LB_SETTOPINDEX,top,0)
EndIf
EndIf
EndIf
proc = GetGadgetData(gadget)
If proc
ProcedureReturn CallWindowProc_(proc,hWnd,msg,wParam,lParam)
EndIf
EndProcedure
Procedure SubClassGadget(gadget,*proc)
SetGadgetData(gadget,SetWindowLongPtr_(GadgetID(gadget),#GWL_WNDPROC,*proc))
EndProcedure
If OpenWindow(0, 0, 0, 480, 300, "Sychronised Swimming", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListViewGadget(0, 10, 10, 225, 280)
ListViewGadget(1, 245,10, 225, 280)
SubClassGadget(0,@Syncro())
SubClassGadget(1,@Syncro())
For a = 1 To 100
AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview 1")
AddGadgetItem (1, -1, "Item " + Str(a) + " of the Listview 2")
Next
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Code: Select all
Procedure MouseOverGadget(window,gadget)
If (WindowMouseX(window) >= GadgetX(gadget)) And (WindowMouseX(window) <= (GadgetX(gadget)+GadgetWidth(gadget)))
If (WindowMouseY(window) >= GadgetY(gadget)) And (WindowMouseY(window) <= (GadgetY(gadget)+GadgetHeight(gadget)))
ProcedureReturn #True
EndIf
EndIf
EndProcedure
Procedure Syncro(hWnd,msg,wParam,lParam)
Static activeGadgetID=0
gadget = GetWindowLongPtr_(hWnd,#GWL_ID)
If msg = #WM_VSCROLL
If gadget = 0 ; ListView
If MouseOverGadget(0,0)
activeGadgetID=hWnd
EndIf
If activeGadgetID=hWnd
top = SendMessage_( hWnd ,#LB_GETTOPINDEX ,0,0)
top2 = SendMessage_(GadgetID(1),#LVM_GETTOPINDEX,0,0)
SendMessage_(GadgetID(1),#LVM_GETITEMPOSITION,top2,origin.POINT) ; get pos of top item
SendMessage_(GadgetID(1),#LVM_GETITEMPOSITION,top,item.POINT) ; get pos of item we want at top
SendMessage_(GadgetID(1),#LVM_SCROLL,0,item\y - origin\y) ; scroll difference
EndIf
ElseIf gadget = 1 ; ListIcon
If MouseOverGadget(0,1)
activeGadgetID=hWnd
EndIf
If activeGadgetID=hWnd
top = SendMessage_(hWnd,#LVM_GETTOPINDEX,0,0)
SendMessage_(GadgetID(0),#LB_SETTOPINDEX,top,0)
EndIf
EndIf
EndIf
proc = GetGadgetData(gadget)
If proc
ProcedureReturn CallWindowProc_(proc,hWnd,msg,wParam,lParam)
EndIf
EndProcedure
Procedure SubClassGadget(gadget,*proc)
SetGadgetData(gadget,SetWindowLongPtr_(GadgetID(gadget),#GWL_WNDPROC,*proc))
EndProcedure
If OpenWindow(0, 0, 0, 480, 300, "Sychronised Swimming", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListViewGadget(0, 10, 10, 225, 280)
ListIconGadget(1, 245,10, 225, 280,"Column 1",100)
AddGadgetColumn(1,2,"Column 2",100)
SubClassGadget(0,@Syncro())
SubClassGadget(1,@Syncro())
For a = 1 To 100
AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview")
AddGadgetItem (1, -1, "Item " + Str(a) + Chr(10)+" of the ListIcon")
Next
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Sychronised Swimming
Wow, thanks guys, truly excellent stuff! 

IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- electrochrisso
- Addict
- Posts: 989
- Joined: Mon May 14, 2007 2:13 am
- Location: Darling River
Re: Sychronised Swimming
It would be good to be able to keep sync when using keyboard too. 

PureBasic! Purely the best 

Re: Sychronised Swimming
For ListIcon()
For ListView()
Code: Select all
OpenWindow(0,0,0,415,320,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ContainerGadget(0,5,5,200 - 2 - 17,310)
ListIconGadget(1,0,0,200,310,"Name",170)
CloseGadgetList()
ListIconGadget(2,190,5,200,310,"Name",170)
For i=1 To 500
AddGadgetItem(1,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
AddGadgetItem(2,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
Next
Structure NMLVSCROLL
hdr.NMHDR
dx.l
dy.l
EndStructure
Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
Select uMsg
Case #WM_NOTIFY
Protected *pnmh.NMHDR = lParam
If *pnmh\hwndFrom = GadgetID(2)
If *pnmh\code = #LVN_ENDSCROLL
Protected *pnms.NMLVSCROLL = lParam
Protected LVTI = SendMessage_(GadgetID(2),#LVM_GETTOPINDEX,0,0)
Protected LVCP = SendMessage_(GadgetID(2),#LVM_GETCOUNTPERPAGE,0,0)
If *pnms\dy < 0
SendMessage_(GadgetID(1),#LVM_ENSUREVISIBLE,LVTI,0)
ElseIf *pnms\dy > 0
SendMessage_(GadgetID(1),#LVM_ENSUREVISIBLE,LVTI + LVCP - 1,0)
EndIf
EndIf
EndIf
Case #WM_KEYDOWN ,#WM_MENUSELECT
If wParam=#VK_UP
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEUP,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEUP,0)
ElseIf wParam=#VK_DOWN
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEDOWN,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEDOWN,0)
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
SetWindowCallback(@WindowCallback())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
For ListView()
Code: Select all
OpenWindow(0,0,0,415,320,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ContainerGadget(0,5,5,200 - 2 - 17,310)
ListViewGadget(1,0,0,200,310)
CloseGadgetList()
ListViewGadget(2,190,5,200,310)
For i=1 To 500
AddGadgetItem(1,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
AddGadgetItem(2,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
Next
Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
Select uMsg
Case #WM_CTLCOLORLISTBOX
If lParam = GadgetID(2)
SendMessage_(GadgetID(1),#LB_SETTOPINDEX,GetScrollPos_(GadgetID(2),#SB_VERT),0)
EndIf
Case #WM_KEYDOWN ,#WM_MENUSELECT
If wParam=#VK_UP
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEUP,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEUP,0)
ElseIf wParam=#VK_DOWN
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEDOWN,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEDOWN,0)
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
SetWindowCallback(@WindowCallback())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
- electrochrisso
- Addict
- Posts: 989
- Joined: Mon May 14, 2007 2:13 am
- Location: Darling River
Re: Sychronised Swimming
Hi RASHAD,
I made a quick addition to your listview() code, to match left and right lists to do the same job in the callback, do you know how to get the row select highlight to match as well.
I have been playing but not very successful for the time being.
I made a quick addition to your listview() code, to match left and right lists to do the same job in the callback, do you know how to get the row select highlight to match as well.

I have been playing but not very successful for the time being.

Code: Select all
OpenWindow(0,0,0,415,320,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ContainerGadget(0,5,5,200 - 2 - 17,310)
ListViewGadget(1,0,0,200,310)
CloseGadgetList()
ListViewGadget(2,190,5,200,310)
For i=1 To 500
AddGadgetItem(1,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
AddGadgetItem(2,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
Next
Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
Select uMsg
Case #WM_CTLCOLORLISTBOX
If lParam = GadgetID(1)
SendMessage_(GadgetID(2),#LB_SETTOPINDEX,GetScrollPos_(GadgetID(1),#SB_VERT),0)
EndIf
If lParam = GadgetID(2)
SendMessage_(GadgetID(1),#LB_SETTOPINDEX,GetScrollPos_(GadgetID(2),#SB_VERT),0)
EndIf
Case #WM_KEYDOWN ,#WM_MENUSELECT
If wParam=#VK_UP
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEUP,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEUP,0)
ElseIf wParam=#VK_DOWN
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEDOWN,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEDOWN,0)
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
SetWindowCallback(@WindowCallback())
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
PureBasic! Purely the best 

Re: Sychronised Swimming
Your correction not needed as long as no vertical Scroll Bar for ListView() #1
Not the best but step forward
Not the best but step forward
Code: Select all
OpenWindow(0,0,0,415,320,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ContainerGadget(0,5,5,200 - 2 - 17,310)
ListViewGadget(1,0,0,200,310)
CloseGadgetList()
ListViewGadget(2,190,5,200,310)
For i=1 To 500
AddGadgetItem(1,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
AddGadgetItem(2,-1,"Gadget Item #" + RSet(Str(i),3,"0"))
Next
Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
Select uMsg
Case #WM_CTLCOLORLISTBOX
If lParam = GadgetID(2)
SendMessage_(GadgetID(1),#LB_SETTOPINDEX,GetScrollPos_(GadgetID(2),#SB_VERT),0)
EndIf
Case #WM_KEYDOWN ,#WM_MENUSELECT
If wParam=#VK_UP
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEUP,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEUP,0)
ElseIf wParam=#VK_DOWN
SendMessage_(GadgetID(1),#WM_VSCROLL,#SB_LINEDOWN,0)
SendMessage_(GadgetID(2),#WM_VSCROLL,#SB_LINEDOWN,0)
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
SetWindowCallback(@WindowCallback())
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case 1
SetGadgetState(2, GetGadgetState(1))
Case 2
SetGadgetState(1, GetGadgetState(2))
EndSelect
EndSelect
Until Quit = 1
Egypt my love
- electrochrisso
- Addict
- Posts: 989
- Joined: Mon May 14, 2007 2:13 am
- Location: Darling River
Re: Sychronised Swimming
Good one RASHAD, That does the trick, gives me something to play with
, I should have tried it your way first, silly me was trying to get it to work in the callback and I get stack overflow error.
Thanks


Thanks
PureBasic! Purely the best 

-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Sychronised Scroll Bars Swimming
Just tried Danilo's method for two ListViews (which works great) with two TreeViews.
As they say in London, "not a sausage". i.e. does not work, do not know why.
As they say in London, "not a sausage". i.e. does not work, do not know why.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Sychronised Scroll Bars Swimming
If I add this to the window's Callback:
When #Tree01 is scrolled, the scrollbar of #Tree02 is sychronised with it perfectly - but the Tree itself is not moved 
Edit: If, after #Tree01 is scrolled, the Window is resized slightly, #Tree02 is refreshed to match it's scrollbar position. So looked at using the RedrawWindow_() function, but scrolling a Tree does not make it the event gadget........
Edit2:Tried this in WindowCallback:Still no joy........
Code: Select all
If Msg = #WM_NOTIFY
pos = GetScrollPos_(GadgetID(#Tree01),#SB_VERT)
SetScrollPos_(GadgetID(#Tree02),#SB_VERT,pos,#True)
EndIf

Edit: If, after #Tree01 is scrolled, the Window is resized slightly, #Tree02 is refreshed to match it's scrollbar position. So looked at using the RedrawWindow_() function, but scrolling a Tree does not make it the event gadget........
Edit2:Tried this in WindowCallback:
Code: Select all
If Msg = #WM_NOTIFY
iPosnNew = GetScrollPos_(GadgetID(#TreeFilesOrg),#SB_VERT)
SetScrollPos_(GadgetID(#TreeFilesPrv),#SB_VERT,iPosnNew,#True)
RedrawWindow_(GadgetID(#Tree02), #Null, #Null, #RDW_UPDATENOW)
EndIf
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Sychronised Scroll Bars Swimming
Finally, an ugly hack that nearly works. The tree sizes are identical, so not sure why they synch perfectly at the top of the scroll limit but are a row out at the bottom of the scroll limit?
Code: Select all
Procedure WindowCallback(hWnd.i, Msg.i, WParam.i, LParam.i)
;----------------------------------------------------------
Static iPosnNew.i, iPosnOld.i
If Msg = #WM_NOTIFY
iPosnNew = GetScrollPos_(GadgetID(#Tree01),#SB_VERT)
If(iPosnNew <> iPosnOld)
SetScrollPos_(GadgetID(#Tree02),#SB_VERT,iPosnNew,#True)
ResizeGadget(#Tree02,#PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(#Tree01) + 1)
ResizeGadget(#Tree02,#PB_Ignore, #PB_Ignore, #PB_Ignore, GadgetHeight(#Tree01))
iPosnOld = iPosnNew
EndIf
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: Synchronised Scroll Bars Swimming
Not sure if this is what your looking for - if it is you had it mostly right originally
- works with both treeviews

- works with both treeviews
Code: Select all
Global lpPrevWndFunc
Procedure TreeGadgetProc(hWnd, Msg, wParam, lParam)
Result = CallWindowProc_(lpPrevWndFunc, hWnd, Msg, wParam, lParam)
Select Msg
Case #WM_VSCROLL
Select hWnd
Case GadgetID(0)
ScrollPos = GetScrollPos_(GadgetID(0), #SB_VERT)
SetScrollPos_(GadgetID(1), #SB_VERT, ScrollPos, #True)
SendMessage_(GadgetID(1), #WM_SETREDRAW, #True, 0)
Case GadgetID(1)
ScrollPos = GetScrollPos_(GadgetID(1), #SB_VERT)
SetScrollPos_(GadgetID(0), #SB_VERT, ScrollPos, #True)
SendMessage_(GadgetID(0), #WM_SETREDRAW, #True, 0)
EndSelect
EndSelect
ProcedureReturn Result
EndProcedure
If OpenWindow(0, 0, 0, 355, 180, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TreeGadget(0, 10, 10, 160, 160)
TreeGadget(1, 180, 10, 160, 160, #PB_Tree_CheckBoxes | #PB_Tree_NoLines)
lpPrevWndFunc = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @TreeGadgetProc())
lpPrevWndFunc = SetWindowLong_(GadgetID(1), #GWL_WNDPROC, @TreeGadgetProc())
For ID = 0 To 1
For a = 0 To 10
AddGadgetItem (ID, -1, "Normal Item "+Str(a), 0, 0)
AddGadgetItem (ID, -1, "Node "+Str(a), 0, 0)
AddGadgetItem(ID, -1, "Sub-Item 1", 0, 1)
AddGadgetItem(ID, -1, "Sub-Item 2", 0, 1)
AddGadgetItem(ID, -1, "Sub-Item 3", 0, 1)
AddGadgetItem(ID, -1, "Sub-Item 4", 0, 1)
AddGadgetItem (ID, -1, "File "+Str(a), 0, 0)
Next
Next
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
If you're not investing in yourself, you're falling behind.
My PureBasic Stuff ➤ FREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Synchronised Scroll Bars Swimming
Well, that's exactly what I was looking for - I don't think my code was anywhere near it really. Thanks JHPJHP.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Kwai chang caine
- Always Here
- Posts: 5494
- Joined: Sun Nov 05, 2006 11:42 pm
- Location: Lyon - France
Re: Synchronised Scroll Bars Swimming
I want to synchronize two listicons.
I don't understand i have tested the code above of fluidbyte given by RASHAD and that not works here
http://www.purebasic.fr/english/viewtop ... 52#p378852
I have found also the code of DANILO but it's for two listview or one ListView and one ListIcon and apparently the behaviour is not the same
http://www.purebasic.fr/english/viewtop ... b7#p378855
Someone have an example for two ListIcons who works ??
Thanks in advance
I don't understand i have tested the code above of fluidbyte given by RASHAD and that not works here

http://www.purebasic.fr/english/viewtop ... 52#p378852
I have found also the code of DANILO but it's for two listview or one ListView and one ListIcon and apparently the behaviour is not the same
http://www.purebasic.fr/english/viewtop ... b7#p378855
Someone have an example for two ListIcons who works ??
Thanks in advance


Not a destination