czardas Posted August 8, 2011 Share Posted August 8, 2011 (edited) I've modified a little rover's code and tested on windows XP (VM) and windows 7, both 32 bits (changing themes and backgrounds) and seems ok now:The scroll bar is not being set to the original position, so the modifications you made still need some attention. I discovered that leaving the scroll bar set to zero seems to solve the problem with theme changes. Leaving the scroll bar at the starting position when changing the windows theme seems a small concession to make. I think we are nearly there. Thanks! Edited August 8, 2011 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
gcue Posted August 8, 2011 Author Share Posted August 8, 2011 yep - almost there! thank you all for your help =D Link to comment Share on other sites More sharing options...
czardas Posted August 8, 2011 Share Posted August 8, 2011 (edited) From rover's suggestion. Removing two lines from the function I wrote leaves the scroll bar set to zero which seems to solve the problem (as I mentioned in my last post). Thanks everyone for the help, I will be using this. expandcollapse popup#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <GUIScrollBars.au3> #include <ScrollBarConstants.au3> Opt("MustDeclareVars", 1) Global Const $WM_THEMECHANGED = 0x031A Global $cRefresh _Main() Func _Main() Local $nFileMenu, $nExititem, $GUIMsg, $button, $hGUI, $h_cGUI $hGUI = GUICreate("ScrollBar Example", 400, 400, -1, -1) $cRefresh = GUICtrlCreateDummy() ;for on-event and message loop modes $nFileMenu = GUICtrlCreateMenu("File") $nExititem = GUICtrlCreateMenuItem("Exit", $nFileMenu) $button = GUICtrlCreateButton("Test", 300, 10, 80, 30) $h_cGUI = GUICreate("Child GUI", 200, 260, 10, 10, $WS_CHILD, Default, $hGUI) For $i = 0 to 39 Step 2 GUICtrlCreateCheckbox("Check " & $i + 1, 10, 10 + 20 * $i/2, 90, 20) GUICtrlCreateCheckbox("Check " & $i + 2, 110, 10 + 20 * $i/2, 90, 20) Next GUISetState(@SW_SHOW) GUICtrlSetResizing($h_cGUI, $GUI_DOCKALL) GUISwitch($hGUI) GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL") GUIRegisterMsg($WM_THEMECHANGED, "WM_THEMECHANGED") _GUIScrollBars_Init($h_cGUI) _GUIScrollBars_ShowScrollBar($h_cGUI, $SB_HORZ, False) _GUIScrollBars_SetScrollInfoMax($h_cGUI, $SB_VERT, 25) GUISetState() While 1 $GUIMsg = GUIGetMsg() Switch $GUIMsg Case $cRefresh _Refresh($h_cGUI) Case $GUI_EVENT_CLOSE, $nExititem ExitLoop Case $button MsgBox(0, "Test", "") EndSwitch WEnd Exit EndFunc ;==>_Main Func WM_THEMECHANGED($hWnd, $Msg, $wParam, $lParam) #forceref $hWnd, $Msg, $wParam, $lParam GUICtrlSendToDummy($cRefresh) Return $GUI_RUNDEFMSG EndFunc ;==>WM_THEMECHANGED Func _Refresh($hWnd) ;Local $nPos = _GUIScrollBars_GetScrollPos($hWnd, $SB_VERT) ; Get current position ; >>>>>>> REMOVED _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, 0) ; Set the scroll to zero Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT) _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False) _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) ;_GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, $nPos) ; >>>>>>> REMOVED EndFunc Func WM_VSCROLL($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam Local $nScrollCode = BitAND($wParam, 0x0000FFFF) Local $index = -1, $yChar, $yPos Local $Min, $Max, $Page, $Pos, $TrackPos For $x = 0 To UBound($aSB_WindowInfo) - 1 If $aSB_WindowInfo[$x][0] = $hWnd Then $index = $x $yChar = $aSB_WindowInfo[$index][3] ExitLoop EndIf Next If $index = -1 Then Return 0 ; Get all the vertial scroll bar information Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT) $Min = DllStructGetData($tSCROLLINFO, "nMin") $Max = DllStructGetData($tSCROLLINFO, "nMax") $Page = DllStructGetData($tSCROLLINFO, "nPage") ; Save the position for comparison later on $yPos = DllStructGetData($tSCROLLINFO, "nPos") $Pos = $yPos $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos") Switch $nScrollCode Case $SB_TOP ; user clicked the HOME keyboard key DllStructSetData($tSCROLLINFO, "nPos", $Min) Case $SB_BOTTOM ; user clicked the END keyboard key DllStructSetData($tSCROLLINFO, "nPos", $Max) Case $SB_LINEUP ; user clicked the top arrow DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1) Case $SB_LINEDOWN ; user clicked the bottom arrow DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1) Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page) Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page) Case $SB_THUMBTRACK ; user dragged the scroll box DllStructSetData($tSCROLLINFO, "nPos", $TrackPos) EndSwitch ;~ // Set the position and then retrieve it. Due to adjustments ;~ // by Windows it may not be the same as the value set. DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS) _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) ;// If the position has changed, scroll the window and update it $Pos = DllStructGetData($tSCROLLINFO, "nPos") If ($Pos <> $yPos) Then _GUIScrollBars_ScrollWindow($hWnd, 0, $yChar * ($yPos - $Pos)) $yPos = $Pos EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_VSCROLL Edited August 8, 2011 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
rover Posted August 8, 2011 Share Posted August 8, 2011 (edited) That's very helpful, thanks. However the problem still seems to occur when switching from Windows XP theme to Windows Classic theme. I have been trying to figure it out, but it's strange because it appears to work when switching back to the Windows XP theme. I can just imagine a user discovering this bug by accident and not being able to reproduce the circumstances that caused it. Another issue to troubleshoot courtesy of our tormentor MicroSoft _GUIScrollBars_ShowScrollBar() solves the issue with turning off the theme engine when the classic theme is selected (themes off), so scroll position is now retained after theme change. The themechanged message is sent when themes are turned off whereas the message occurs after the old theme is removed and the new theme is set when switching between themes so perhaps the message order/inclusion of painting/erasing is different because of this? @taietel Using _GUIScrollBars_ShowScrollBar(), all code can once more be shoved into message events handlers instead of being polled. Edit: typo, rewording Edit2: just read the posts after czardas post I quoted above, issue with scroll position in taietel's code already addressed by czardas expandcollapse popup#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StructureConstants.au3> #include <GUIScrollBars.au3> #include <ScrollBarConstants.au3> Opt("MustDeclareVars", 1) Global Const $WM_THEMECHANGED = 0x031A Global $cRefresh _Main() Func _Main() Local $nFileMenu, $nExititem, $GUIMsg, $button, $hGUI, $h_cGUI $hGUI = GUICreate("ScrollBar Example", 400, 400, -1, -1) $cRefresh = GUICtrlCreateDummy() ;for on-event and message loop modes $nFileMenu = GUICtrlCreateMenu("File") $nExititem = GUICtrlCreateMenuItem("Exit", $nFileMenu) $button = GUICtrlCreateButton("Test", 300, 10, 80, 30) $h_cGUI = GUICreate("Child GUI", 200, 260, 10, 10, $WS_CHILD, Default, $hGUI) For $i = 0 to 39 Step 2 GUICtrlCreateCheckbox("Check " & $i + 1, 10, 10 + 20 * $i/2, 90, 20) GUICtrlCreateCheckbox("Check " & $i + 2, 110, 10 + 20 * $i/2, 90, 20) Next GUISetState(@SW_SHOW) GUICtrlSetResizing($h_cGUI, $GUI_DOCKALL) GUISwitch($hGUI) GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL") GUIRegisterMsg($WM_THEMECHANGED, "WM_THEMECHANGED") _GUIScrollBars_Init($h_cGUI) _GUIScrollBars_ShowScrollBar($h_cGUI, $SB_HORZ, False) _GUIScrollBars_SetScrollInfoMax($h_cGUI, $SB_VERT, 25) GUISetState() While 1 $GUIMsg = GUIGetMsg() Switch $GUIMsg Case $cRefresh _Refresh($h_cGUI) Case $GUI_EVENT_CLOSE, $nExititem ExitLoop Case $button MsgBox(0, "Test", "") EndSwitch WEnd Exit EndFunc ;==>_Main Func WM_THEMECHANGED($hWnd, $Msg, $wParam, $lParam) #forceref $hWnd, $Msg, $wParam, $lParam GUICtrlSendToDummy($cRefresh) Return $GUI_RUNDEFMSG EndFunc ;==>WM_THEMECHANGED Func _Refresh($hWnd) ;Local $aRet = DllCall('uxtheme.dll', 'int', 'IsThemeActive') ;If @error = 0 And $aRet[0] = 0 Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, True) ;EndIf Local $nPos = _GUIScrollBars_GetScrollPos($hWnd, $SB_VERT) ; Get current position _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, 0) ; Set the scroll to zero Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT) _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False) _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, $nPos) EndFunc Func WM_VSCROLL($hWnd, $Msg, $wParam, $lParam) #forceref $Msg, $wParam, $lParam Local $nScrollCode = BitAND($wParam, 0x0000FFFF) Local $index = -1, $yChar, $yPos Local $Min, $Max, $Page, $Pos, $TrackPos For $x = 0 To UBound($aSB_WindowInfo) - 1 If $aSB_WindowInfo[$x][0] = $hWnd Then $index = $x $yChar = $aSB_WindowInfo[$index][3] ExitLoop EndIf Next If $index = -1 Then Return 0 ; Get all the vertial scroll bar information Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT) $Min = DllStructGetData($tSCROLLINFO, "nMin") $Max = DllStructGetData($tSCROLLINFO, "nMax") $Page = DllStructGetData($tSCROLLINFO, "nPage") ; Save the position for comparison later on $yPos = DllStructGetData($tSCROLLINFO, "nPos") $Pos = $yPos $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos") Switch $nScrollCode Case $SB_TOP ; user clicked the HOME keyboard key DllStructSetData($tSCROLLINFO, "nPos", $Min) Case $SB_BOTTOM ; user clicked the END keyboard key DllStructSetData($tSCROLLINFO, "nPos", $Max) Case $SB_LINEUP ; user clicked the top arrow DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1) Case $SB_LINEDOWN ; user clicked the bottom arrow DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1) Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page) Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page) Case $SB_THUMBTRACK ; user dragged the scroll box DllStructSetData($tSCROLLINFO, "nPos", $TrackPos) EndSwitch ;~ // Set the position and then retrieve it. Due to adjustments ;~ // by Windows it may not be the same as the value set. DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS) _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) ;// If the position has changed, scroll the window and update it $Pos = DllStructGetData($tSCROLLINFO, "nPos") If ($Pos <> $yPos) Then _GUIScrollBars_ScrollWindow($hWnd, 0, $yChar * ($yPos - $Pos)) $yPos = $Pos EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_VSCROLL Edited August 8, 2011 by rover I see fascists... Link to comment Share on other sites More sharing options...
czardas Posted August 8, 2011 Share Posted August 8, 2011 _GUIScrollBars_ShowScrollBar() solves the issue with turning off the theme engine when the classic theme is selected (themes off),so scroll position is now retained after theme change.Interesting discovery! Thanks for all the explanations. V. Good! operator64 ArrayWorkshop 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