buymeapc Posted June 19, 2015 Share Posted June 19, 2015 (edited) Hi all,I've been searching throughout the forums and I can't really find a solution to my problem. I have a child window that has two listviews and I need their scrolling to be synchronized. Using a reference to a post by Mat, I slapped together a quick replicator that will show the issue. If the scrollbars are dragged too quickly, they become out of sync.Is there a way I can properly synchronize these scrollbars no matter the speed of the scrolling?expandcollapse popup#include <GUIConstantsEx.au3> #include <SendMessage.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <ListViewConstants.au3> Global $hGUI, $hList1, $hList2 $hGUI = GUICreate("Demo", 400, 400) $Button = GUICtrlCreateButton("Click Me", 150, 188, 100, 24) GUISetState(@SW_SHOW, $hGUI) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $Button _GUI_ListViews() EndSwitch WEnd Func _GUI_ListViews() $hGUILV = GUICreate("Testing scroll", 500, 600, -1, -1, -1, -1, $hGUI) $hList1 = GUICtrlCreateListView("List view 1", 2, 2, 248, 596) $hList2 = GUICtrlCreateListView("List view 2", 253, 2, 249, 596) GUISetState(@SW_SHOW, $hGUILV) For $i = 1 To 500 GUICtrlCreateListViewItem($i, $hList1) GUICtrlCreateListViewItem($i, $hList2) Next While 1 Sleep(10) If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop WEnd GUIDelete($hGUILV) EndFunc Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) If DllStructGetData($tNMHDR, "code") <> $LVN_ENDSCROLL Then Return Local $hListFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) Local $tNMLVSCROLL = DllStructCreate($tagNMLVSCROLL, $lParam) If $hListFrom = GUICtrlGetHandle($hList1) Then GUICtrlSendMsg($hList2, $LVM_SCROLL, DllStructGetData($tNMLVSCROLL, "dx"), DllStructGetData($tNMLVSCROLL, "dy") * 16) ElseIf $hListFrom = GUICtrlGetHandle($hList2) Then GUICtrlSendMsg($hList1, $LVM_SCROLL, DllStructGetData($tNMLVSCROLL, "dx"), DllStructGetData($tNMLVSCROLL, "dy") * 16) EndIf EndFunc ;==>WM_NOTIFY Edited June 19, 2015 by buymeapc Link to comment Share on other sites More sharing options...
UEZ Posted June 19, 2015 Share Posted June 19, 2015 Something like this here?expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiTreeView.au3> #include <GuiListView.au3> #include <Misc.au3> #include <GuiScrollBars.au3> Global Const $iMax = 40 $hGUI = GUICreate("Synchro Pair", 195, 240, -1, -1) $cLV_2 = GUICtrlCreateListView("LV_2", 60, 5, 85, 220) $hLV_2 = GUICtrlGetHandle($cLV_2) GUISetState(@SW_SHOW) $hGUI_Child = GUICreate("", 50, 220, 10, 5, $WS_POPUP, $WS_EX_MDICHILD, $hGUI) $cLV_1 = GUICtrlCreateListView("LV_1", 0, 0, 85, 220) $hLV_1 = GUICtrlGetHandle($cLV_1) GUISetState() For $i = 1 To $iMax GUICtrlCreateListViewItem("Item " & $i, $cLV_1) GUICtrlCreateListViewItem("Item " & $i, $cLV_2) Next Global $aRect = _GUICtrlListView_GetItemRect($hLV_2, 0) Global Const $iDeltaY = $aRect[3] - $aRect[1] GUIRegisterMsg($WM_NOTIFY, "_WM_Notify") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func _WM_Notify($hWnd, $Msg, $wParam, $lParam) Local Const $iLines = _SendMessage($hLV_2, $LVM_GETTOPINDEX) - _SendMessage($hLV_1, $LVM_GETTOPINDEX) _SendMessage($hLV_1, $LVM_SCROLL, 0, $iLines * $iDeltaY) Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_Notify argumentum 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
mikell Posted June 20, 2015 Share Posted June 20, 2015 (edited) UEZ,Your code works nice on 2 listviews in the main gui , but I can't get it to work if the listviews are in a dedicated child gui (like the one in the 1st post) EditSorry, my bad, it was a stupid saturday typo expandcollapse popup#include <GUIConstantsEx.au3> #include <SendMessage.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> Global $hGUI, $hList1, $hList2, $hLV_1, $hLV_2 $hGUI = GUICreate("Demo", 400, 400) $Button = GUICtrlCreateButton("Click Me", 150, 188, 100, 24) GUISetState(@SW_SHOW, $hGUI) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $Button _GUI_ListViews() EndSwitch WEnd Func _GUI_ListViews() $hGUILV = GUICreate("Testing scroll", 500, 600, -1, -1) $cLV_2 = GUICtrlCreateListView("List view 2", 253, 2, 248, 596) $hLV_2 = GUICtrlGetHandle($cLV_2) GUISetState(@SW_SHOW) $hGUI_Child = GUICreate("", 249, 600, 0, 0, $WS_CHILD, -1, $hGUILV) $cLV_1 = GUICtrlCreateListView("List view 1", 2, 2, 246, 596) $hLV_1 = GUICtrlGetHandle($cLV_1) GUISetState() For $i = 1 To 500 GUICtrlCreateListViewItem("Item " & $i, $cLV_1) GUICtrlCreateListViewItem("Item " & $i, $cLV_2) Next Global $aRect = _GUICtrlListView_GetItemRect($hLV_2, 0) Global Const $iDeltaY = $aRect[3] - $aRect[1] GUIRegisterMsg($WM_NOTIFY, "_WM_Notify") While 1 Sleep(10) If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop WEnd GUIDelete($hGUILV) EndFunc Func _WM_Notify($hWnd, $Msg, $wParam, $lParam) Local Const $iLines = _SendMessage($hLV_2, $LVM_GETTOPINDEX) - _SendMessage($hLV_1, $LVM_GETTOPINDEX) _SendMessage($hLV_1, $LVM_SCROLL, 0, $iLines * $iDeltaY) Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_Notify Edited June 20, 2015 by mikell Link to comment Share on other sites More sharing options...
AutoBert Posted June 20, 2015 Share Posted June 20, 2015 (edited) In UEZ's Script the childGUI is created in the mainGUI. It also works in separetet GUI's:#include <GUIConstantsEx.au3>#include <WindowsConstants.au3>#include <GuiTreeView.au3>#include <GuiListView.au3>#include <Misc.au3>#include <GuiScrollBars.au3>Global Const $iMax = 40$hGUI = GUICreate("Synchro Pair", 195, 240, -1, -1)$cLV_2 = GUICtrlCreateListView("LV_2", 60, 5, 85, 220)$hLV_2 = GUICtrlGetHandle($cLV_2)GUISetState(@SW_SHOW)$hGUI_Child = GUICreate("Child", 50, 220, 10, 5)$cLV_1 = GUICtrlCreateListView("LV_1", 0, 0, 85, 220)$hLV_1 = GUICtrlGetHandle($cLV_1)GUISetState()For $i = 1 To $iMax GUICtrlCreateListViewItem("Item " & $i, $cLV_1) GUICtrlCreateListViewItem("Item " & $i, $cLV_2)NextGlobal $aRect = _GUICtrlListView_GetItemRect($hLV_2, 0)Global Const $iDeltaY = $aRect[3] - $aRect[1]GUIRegisterMsg($WM_NOTIFY, "_WM_Notify")While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitchWEndFunc _WM_Notify($hWnd, $Msg, $wParam, $lParam) Local Const $iLines = _SendMessage($hLV_2, $LVM_GETTOPINDEX) - _SendMessage($hLV_1, $LVM_GETTOPINDEX) _SendMessage($hLV_1, $LVM_SCROLL, 0, $iLines * $iDeltaY) Return "GUI_RUNDEFMSG"EndFunc ;==>_WM_Notify Edited June 20, 2015 by AutoBert Link to comment Share on other sites More sharing options...
buymeapc Posted June 22, 2015 Author Share Posted June 22, 2015 (edited) UEZ,Your code works nice on 2 listviews in the main gui , but I can't get it to work if the listviews are in a dedicated child gui (like the one in the 1st post) EditSorry, my bad, it was a stupid saturday typo expandcollapse popup#include <GUIConstantsEx.au3> #include <SendMessage.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> Global $hGUI, $hList1, $hList2, $hLV_1, $hLV_2 $hGUI = GUICreate("Demo", 400, 400) $Button = GUICtrlCreateButton("Click Me", 150, 188, 100, 24) GUISetState(@SW_SHOW, $hGUI) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $Button _GUI_ListViews() EndSwitch WEnd Func _GUI_ListViews() $hGUILV = GUICreate("Testing scroll", 500, 600, -1, -1) $cLV_2 = GUICtrlCreateListView("List view 2", 253, 2, 248, 596) $hLV_2 = GUICtrlGetHandle($cLV_2) GUISetState(@SW_SHOW) $hGUI_Child = GUICreate("", 249, 600, 0, 0, $WS_CHILD, -1, $hGUILV) $cLV_1 = GUICtrlCreateListView("List view 1", 2, 2, 246, 596) $hLV_1 = GUICtrlGetHandle($cLV_1) GUISetState() For $i = 1 To 500 GUICtrlCreateListViewItem("Item " & $i, $cLV_1) GUICtrlCreateListViewItem("Item " & $i, $cLV_2) Next Global $aRect = _GUICtrlListView_GetItemRect($hLV_2, 0) Global Const $iDeltaY = $aRect[3] - $aRect[1] GUIRegisterMsg($WM_NOTIFY, "_WM_Notify") While 1 Sleep(10) If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop WEnd GUIDelete($hGUILV) EndFunc Func _WM_Notify($hWnd, $Msg, $wParam, $lParam) Local Const $iLines = _SendMessage($hLV_2, $LVM_GETTOPINDEX) - _SendMessage($hLV_1, $LVM_GETTOPINDEX) _SendMessage($hLV_1, $LVM_SCROLL, 0, $iLines * $iDeltaY) Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_Notify Thank you all for the examples. Mikell's was the closest to what I'm looking for, but unfortunately, it can't be opened more than once without crashing due to the constant being re-declared. Is there a way around this? Otherwise, it's perfect, I think.Ok, I just made the constant a global variable and it's all good. Thank you all for the help!! Edited June 22, 2015 by buymeapc Link to comment Share on other sites More sharing options...
argumentum Posted November 14, 2016 Share Posted November 14, 2016 (edited) On 6/19/2015 at 5:31 PM, UEZ said: Something like this here? ok, now I, need the bottom scrollbar to sync up. I've modified your example to exemplify my view expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiTreeView.au3> #include <GuiListView.au3> #include <Misc.au3> #include <GuiScrollBars.au3> #include <WinAPI.au3> Global Const $iMax = 40 Local $s, $n $hGUI = GUICreate("Synchro Pair - 2.0 ???", 455, 240, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP), BitOR($WS_EX_ACCEPTFILES, $WS_EX_WINDOWEDGE)) $cLV_2 = GUICtrlCreateListView("LV_2 - A|B|C|D|E|F|G|H|I|J|K|L", 160, 25, 285, 160) $hLV_2 = GUICtrlGetHandle($cLV_2) GUISetState(@SW_SHOW) ;~ $hGUI_Child = GUICreate("", 150, 220, 10, 5, $WS_POPUP, $WS_EX_MDICHILD, $hGUI) $cLV_1 = GUICtrlCreateListView("LV_1 - A|B|C|D|E|F|G|H|I|J|K|L", 5, 5, 150, 220) $hLV_1 = GUICtrlGetHandle($cLV_1) GUISetState() ;ConsoleWrite('--- $cLV_1 = ' & $cLV_1 & ' / $hLV_1 = ' & $hLV_1 & @CRLF) ;ConsoleWrite('--- $cLV_2 = ' & $cLV_2 & ' / $hLV_2 = ' & $hLV_2 & @CRLF) Local $s, $n For $i = 1 To $iMax $s = "" For $n = 0 To 10 $s &= "Item " & $i & " " & Chr(Asc("A") + $n) & "|" Next $s &= "Item " & $i & " " & Chr(Asc("A") + $n) ;~ ConsoleWrite($s&@CRLF) GUICtrlCreateListViewItem($s, $cLV_1) GUICtrlCreateListViewItem($s, $cLV_2) Next Global $aRect = _GUICtrlListView_GetItemRect($hLV_2, 0) Global Const $iDeltaY = $aRect[3] - $aRect[1] GUIRegisterMsg($WM_NOTIFY, "_WM_Notify") #Region SIZEBOX Global Const $SBS_SIZEBOX = 0x08 Global $hSizebox = _WinAPI_CreateWindowEx(0, "Scrollbar", "", $WS_CHILD + $WS_VISIBLE + $SBS_SIZEBOX, 300 - 20, 200 - 20, 20, 20, $hGUI) GUIRegisterMsg($WM_SIZE, "WM_SIZE") _Sizebox__Resize($hSizebox) _WinAPI_RedrawWindow($hGUI) ; to show the $SBS_SIZEBOX Func _Sizebox__Resize($hCtrl) Local $aSize = WinGetClientSize($hGUI) If UBound($aSize) = 2 Then WinMove($hCtrl, "", $aSize[0] - 20, $aSize[1] - 20) EndFunc ;==>_Sizebox__Resize ; Resize the status bar when GUI size changes Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam _Sizebox__Resize($hSizebox) Return $GUI_RUNDEFMSG EndFunc ;==>WM_SIZE #EndRegion SIZEBOX While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIDelete($hGUI) ExitLoop EndSwitch WEnd Func _WM_Notify($hWnd, $Msg, $wParam, $lParam) ;ConsoleWrite('+ Func _WM_Notify("' & $hWnd & '", "' & $Msg & '", "' & $wParam & '", "' & $lParam & '")' & @CRLF) If $cLV_2 = $wParam Then ; to make both scrollers work Local $iLines = _SendMessage($hLV_2, $LVM_GETTOPINDEX) - _SendMessage($hLV_1, $LVM_GETTOPINDEX) _SendMessage($hLV_1, $LVM_SCROLL, 0, $iLines * $iDeltaY) EndIf If $cLV_1 = $wParam Then Local $iLines = _SendMessage($hLV_1, $LVM_GETTOPINDEX) - _SendMessage($hLV_2, $LVM_GETTOPINDEX) _SendMessage($hLV_2, $LVM_SCROLL, 0, $iLines * $iDeltaY) EndIf Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_Notify can you @UEZ add the bottom too ? ( actually anyone who'd know how ) Edited November 14, 2016 by argumentum prettify the example code Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
mikell Posted November 14, 2016 Share Posted November 14, 2016 Here is my try ... expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #include <GuiScrollBars.au3> $hGUI = GUICreate("Synchro Pair - 2.0 ???", 455, 240, -1, -1) $cLV_1 = GUICtrlCreateListView("LV_1 A|B|C|D|E|F|G|H|I|J|K|L", 5, 5, 190, 220) $hLV_1 = GUICtrlGetHandle($cLV_1) $cLV_2 = GUICtrlCreateListView("LV_2 A|B|C|D|E|F|G|H|I|J|K|L", 240, 5, 190, 220) $hLV_2 = GUICtrlGetHandle($cLV_2) GUISetState() For $i = 1 To 40 $s = "" For $n = 0 To 10 $s &= "Item " & $i & " " & Chr(Asc("A") + $n) & "|" Next GUICtrlCreateListViewItem($s, $cLV_1) GUICtrlCreateListViewItem($s, $cLV_2) Next Global $aRect = _GUICtrlListView_GetItemRect($hLV_2, 0) Global Const $iDeltaY = $aRect[3] - $aRect[1] GUIRegisterMsg($WM_NOTIFY, "_WM_Notify") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIDelete($hGUI) ExitLoop EndSwitch WEnd Func _WM_Notify($hWnd, $Msg, $wParam, $lParam) If $cLV_2 = $wParam Then ; to make both scrollers work $x1 = _GUIScrollBars_GetScrollPos($hLV_1, $SB_HORZ) $x2 = _GUIScrollBars_GetScrollPos($hLV_2, $SB_HORZ) Local $iLines = _GUICtrlListView_GetTopIndex($hLV_2) - _GUICtrlListView_GetTopIndex($hLV_1) _GUICtrlListView_Scroll ($hLV_1, $x2-$x1, $iLines * $iDeltaY) EndIf If $cLV_1 = $wParam Then $x1 = _GUIScrollBars_GetScrollPos($hLV_1, $SB_HORZ) $x2 = _GUIScrollBars_GetScrollPos($hLV_2, $SB_HORZ) Local $iLines = _GUICtrlListView_GetTopIndex($hLV_1) - _GUICtrlListView_GetTopIndex($hLV_2) _GUICtrlListView_Scroll ($hLV_2, $x1-$x2, $iLines * $iDeltaY) EndIf Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_Notify argumentum 1 Link to comment Share on other sites More sharing options...
argumentum Posted November 15, 2016 Share Posted November 15, 2016 (edited) 9 hours ago, mikell said: Here is my try ... Well, your try, is perfect !. Very many thanks expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> #include <GuiScrollBars.au3> Global $hGUI = GUICreate("Synchro Pair - 2.0 ;)", 455, 240, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP), BitOR($WS_EX_ACCEPTFILES, $WS_EX_WINDOWEDGE)) Global $cLV_2 = GUICtrlCreateListView("LV_2 - A|B|C|D|E|F|G|H|I|J|K|L", 160, 45, 285, 160) Global $hLV_2 = GUICtrlGetHandle($cLV_2) Global $cLV_1 = GUICtrlCreateListView("LV_1 - A|B|C|D|E|F|G|H|I|J|K|L", 5, 5, 150, 220) Global $hLV_1 = GUICtrlGetHandle($cLV_1) GUISetState(@SW_SHOW) PopulateListViewDemo() Func PopulateListViewDemo() Local $s, $n, $i For $i = 1 To 40 $s = "" For $n = 0 To 10 $s &= "Item " & $i & " " & Chr(Asc("A") + $n) & "|" Next $s &= "Item " & $i & " " & Chr(Asc("A") + $n) GUICtrlCreateListViewItem($s, $cLV_1) GUICtrlCreateListViewItem($s, $cLV_2) Next EndFunc ;==>fillDemo GUIRegisterMsg($WM_NOTIFY, "_WM_Notify") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIDelete($hGUI) ExitLoop EndSwitch WEnd Func _WM_Notify($hWnd, $Msg, $wParam, $lParam) Switch $wParam Case $cLV_2 _GUICtrlListView_SyncScroll($hLV_2, $hLV_1) Case $cLV_1 _GUICtrlListView_SyncScroll($hLV_1, $hLV_2) EndSwitch Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_Notify Func _GUICtrlListView_SyncScroll($hWndControler, $hWndControled) ;Local Static $aRect = _GUICtrlListView_GetItemRect($hWndControler, 0) ; the result is usually 14 Local Static $iDeltaY = 14 ; $aRect[3] - $aRect[1] ; so, set as 14 or remove the "Static" Local $x1 = _GUIScrollBars_GetScrollPos($hWndControled, $SB_HORZ) ; otherwise the Static could set to 0 Local $x2 = _GUIScrollBars_GetScrollPos($hWndControler, $SB_HORZ) ; if no entry in the listview when first called ! Local $iLines = _GUICtrlListView_GetTopIndex($hWndControler) - _GUICtrlListView_GetTopIndex($hWndControled) _GUICtrlListView_Scroll($hWndControled, $x2 - $x1, $iLines * $iDeltaY) EndFunc ;==>_GUICtrlListView_SyncScroll Edited November 15, 2016 by argumentum show how I will use your code Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now