Jump to content
Melba23

Scrollbars Made Easy - New version 13 May 18

Recommended Posts

ScriptJunky

I found a pretty fatal bug in this UDF. It is present in the examples provided in the .zip and is present anytime I use this UDF in my own scripts.
To show you how to re-create this bug, just follow these steps exactly, using one of the examples provided with the UDF:

1) run the script "GUIScrollbars_Size_Example_2.au3"
2) scroll to the bottom
3) maximize the window
4) scroll up

At this point the scrollbars re-generate as if I was scrolled all the way up, but the vertical scroll bar is still at the bottom, so now, the bottom part of the previously scrollable area is cutoff, and when you scroll up, there is an equally sized area of blank space at the top. (in the screenshot I added more labels than the default to show the extent of the issue) 

 

SBbug.jpg

Share this post


Link to post
Share on other sites
Melba23
Posted (edited)

ScriptJunky,

Add a MAXIMIZE event to call the _GUIScrollbars_Restore function - that should solve the problem:

Case $GUI_EVENT_RESTORE, $GUI_EVENT_MAXIMIZE
    _GUIScrollbars_Restore($hGUI, True, False)

M23

Edited by Melba23
Fixed code tags

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
ScriptJunky
2 hours ago, Melba23 said:

ScriptJunky,

Add a MAXIMIZE event to call the _GUIScrollbars_Restore function - that should solve the problem:

Case $GUI_EVENT_RESTORE, $GUI_EVENT_MAXIMIZE
    _GUIScrollbars_Restore($hGUI, True, False)

M23

I tried this but I didn't notice the optional parameters, I was just using the winhandle. What exactly do the second and third parameters define? (sorry im not at my desk, otherwise I would figure it out myself 🤗) 

Share this post


Link to post
Share on other sites
Melba23

ScriptJunky,

Neither was I - which is why I can not properly test my suggestion. The parameters are:

; Parameters ....: $hWnd  -> GUI containing scrollbars
;                  $fVert -> True (default) = vertical scrollbar visible; False = vertical scrollbar not visible
;                  $fHorz -> True (default) = horizontal scrollbar visible; False = horzontal scrollbar not visible

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
ScriptJunky
6 hours ago, Melba23 said:

ScriptJunky,

Add a MAXIMIZE event to call the _GUIScrollbars_Restore function - that should solve the problem:

Case $GUI_EVENT_RESTORE, $GUI_EVENT_MAXIMIZE
    _GUIScrollbars_Restore($hGUI, True, False)

M23

Unfortunately, this solution, just changes the problem. It corrects the extra space at the top, but the bottom is still cutoff substantially. In the following screenshot I added 99 labels, and after scrolling down then maximizing, the area is cutoff at the 33rd label, so 2/3rd's are missing somewhere.

scrollbarsbug.jpg

Share this post


Link to post
Share on other sites
Melba23

ScriptJunky,

Just got back onto my machine and I see the same thing - it is because the MAXIMIZE resets all the control sizes and the size of the aperture to scroll. So we need to do a bit of calculation - this seems to work:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIScrollBars.au3>
#include <ScrollBarConstants.au3>

#include "GUIScrollbars_Size.au3"

Global $ahLabels[100] = [0], $iCount = 10

$hGUI = GUICreate("Test", 300, 300, -1, -1, $WS_OVERLAPPEDWINDOW)

GUISetState()

$aRet = _GUIScrollbars_Size(0, 550, 300, 300)

GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")

_GUIScrollBars_Init($hGUI)
_GUIScrollBars_ShowScrollBar($hGUI, $SB_VERT, True)
_GUIScrollBars_ShowScrollBar($hGUI, $SB_HORZ, False)
_GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
_GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])

$hButton = GUICtrlCreateButton("Change number of labels", 10, 10, 265, 30)

_Draw_Labels(10)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_RESTORE
            _GUIScrollbars_Restore($hGUI, True, False)
        Case $GUI_EVENT_MAXIMIZE
            $aCtrlPos_1 = ControlGetPos($hGUI, "", $ahLabels[1])
            $aCtrlPos_2 = ControlGetPos($hGUI, "", $ahLabels[2])
            $aClientSize = WinGetClientSize($hGUI)
            $aRet = _GUIScrollbars_Size(0, ($iCount + 1) * ($aCtrlPos_2[1] - $aCtrlPos_1[1]), $aClientSize[0], $aClientSize[1])
            _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
            _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])
        Case $hButton
            Do
                $iCount = Number(InputBox("Resize scroll area", "Select number of labels to display (min 6)", "", "", 240, 130))
            Until $iCount > 5

             _Draw_labels($iCount)
            $aRet = _GUIScrollbars_Size(0, ($iCount + 1) * 50, 300, 300)
            _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
            _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])
    EndSwitch

WEnd

Func _Draw_labels($iCount)

    GUISwitch($hGUI)

    If $iCount > $ahLabels[0] Then
        For $i = $ahLabels[0] + 1 To $iCount
            $ahLabels[$i] = GUICtrlCreateLabel($i, 10, $i * 50, 265, 40)
            GUICtrlSetBkColor(-1, 0xFF8080)
            GUICtrlSetFont(-1, 18)
        Next
    Else
        For $i = $iCount + 1 To $ahLabels[0]
            GUICtrlDelete($ahLabels[$i])
        Next
    EndIf
    $ahLabels[0] = $iCount

EndFunc

Func _Scrollbars_WM_VSCROLL($hWnd, $Msg, $wParam, $lParam)

    #forceref $Msg, $wParam, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
    Local $iIndex = -1, $yChar, $yPos
    Local $Min, $Max, $Page, $Pos, $TrackPos

    For $x = 0 To UBound($__g_aSB_WindowInfo) - 1
        If $__g_aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $yChar = $__g_aSB_WindowInfo[$iIndex][3]
            ExitLoop
        EndIf
    Next
    If $iIndex = -1 Then Return 0

    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    $yPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $yPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")

    Switch $nScrollCode
        Case $SB_TOP
            DllStructSetData($tSCROLLINFO, "nPos", $Min)
        Case $SB_BOTTOM
            DllStructSetData($tSCROLLINFO, "nPos", $Max)
        Case $SB_LINEUP
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
        Case $SB_LINEDOWN
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
        Case $SB_PAGEUP
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
        Case $SB_PAGEDOWN
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
        Case $SB_THUMBTRACK
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)

    $Pos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($Pos <> $yPos) Then
        _GUIScrollBars_ScrollWindow($hWnd, 0, $yChar * ($yPos - $Pos))
        $yPos = $Pos
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_VSCROLL

That works for me - over to you to break it again!

M23

  • Haha 1

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
ScriptJunky

It will be my pleasure ;) Ill give it a go and see if it works for me. Thank you so much for your assistance. Sadly, I have been scripting in autoit since about 2003-ish (was one of the first languages that I ever learned) and I've never taken the time to properly learn scrollbars. I never even used them until this UDF was release way back when, and even now in 2018 its still my go to for scroll bars :D. Thanks again! 

Share this post


Link to post
Share on other sites
ScriptJunky
20 minutes ago, Melba23 said:

That works for me - over to you to break it again!

Mission Accomplished! I have succeeded in breaking it again. :(

Ok so this time, in the screenshot, i added 99 labels, scrolled down to the bottom, maximized, and this was the result:

(I would also like to note that, after it glitched like this, I minimized it then restored it back to its maximized state and it fixed itself. Furthermore I would like to note that I am a magnet for bugs :sweating:

scrollbarsbug.jpg

Share this post


Link to post
Share on other sites
ScriptJunky

Oh I forgot to mention, in this trial, after the maximizing part, I was only able to scroll to the 76th label, and there was a bunch of empty space above where the screenshot was taken.

Share this post


Link to post
Share on other sites
ScriptJunky

Sorry I keep posting so much, but in addition to the last 2 post, I re-created the error, then un-maximized it after maximizing then the aperture increases in size like 3-fold. Hope that helps somehow in figuring out the problem :P 

scrollbarsbug.jpg

Share this post


Link to post
Share on other sites
ScriptJunky
Posted (edited)

I would like to suggest an addition to this UDF. I noticed an issue where if you specify there to not be any horizontal width to the aperture, or have a smaller width aperture than the gui, then when you create the scrollbars, it does not show a horizontal bar, but after minimizing using _GUIScrollbars_Minimize() and then restoring with _GUIScrollbars_Restore() it, by default, adds in the horizontal scrollbar (with no scroll range) unless you specify the third parameter of _GUIScrollbars_Restore() as False (and the same goes for vertical scrolling) but maybe perhaps adding in an internal check to see if there is a horizontal/vertical scroll to begin with, maybe something like this:
 

Func _GUIScrollbars_Restore($hWnd, $fVert = True , $fHorz = True)

; Get client area dimensions $hWnd
Local $a = DllStructCreate("struct;long;long;long;long;endstruct")
Local $b=DllCall("user32.dll","bool","GetClientRect","hwnd",$hWnd,"struct*",$a) 
Local $c[2]=[DllStructGetData($b,3)-DllStructGetData($b,1),DllStructGetData($b,4)-DllStructGetData($b,2)] 

; If the aperture dimensions are smaller than the client dimensions, disable the corresponding dimension's scrollbar
Local $aAperture[2] = [$iH_Scroll, $iV_Scroll] ; replace this with values from _GUIScrollbars_Generate() or wherever they're stored
If $aAperture[0] <= $c[0] then $fHorz = False ; possibly subtract the width of the vertical scroll bar using the value from GetSystemMetrics ??
If $aAperture[1] <= $c[1] then $fVert = False ; possibly subtract the height of the horizontal scroll bar using the value from GetSystemMetrics ??

 As for now, without editing the UDF, I made a workaround for this issue: 

Local $aV=DllCall("user32.dll","bool","GetScrollRange","hwnd",$hwnd,"int",1,"int*",0,"int*",0),$v=1
Local $aH=DllCall("user32.dll","bool","GetScrollRange","hwnd",$hwnd,"int",0,"int*",0,"int*",0),$h=1
If $aV[4]=100 Then $v=0
If $aH[4]=100 Then $h=0
_GUIScrollbars_Restore($hwnd,$v,$h)

Anyways, regarding the last 3 posts, I have decided just to remove the ability to maximize from my script until I can figure out whats going on :blink:

 

Edited by ScriptJunky

Share this post


Link to post
Share on other sites
TJF

I am generating a GUI (Scroll-Area) and while reading in a music-biblio the scroll-area fills itself with many thumbnails of the music-albums. While this filling of the scroll-area the scroll-area must be disabled. Otherwise, while srolling, there would be empty white areas ... At the start of the procedure I want to disable the scroll-area (until it is finished) with

GUISetState(@SW_DISABLE, $hGUI)

That disables only the scrollbar, but not the mouse-scroll behaviour inside the sroll-area. What would you suggest?

Here a modified file:

#include <GUIConstantsEx.au3>
#include "GUIScrollbars_Ex.au3"

; Create GUI with red background
$hGUI = GUICreate("Test", 500, 500)
GUISetBkColor(0xFF0000, $hGUI)
; To get cursor keys to scroll GUI, create controls AFTER GUISetState
GUISetState()

; Create labels to show scrolling
GUICtrlCreateLabel("", 0, 0, 500, 500)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlCreateLabel("", 500, 500, 500, 500)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlCreateLabel("", 0, 500, 500, 500)
GUICtrlSetBkColor(-1, 0x0000FF)
GUICtrlCreateLabel("", 500, 0, 500, 500)
GUICtrlSetBkColor(-1, 0x0000FF)

GUICtrlCreateLabel("", 990, 990, 10, 10)
GUICtrlSetBkColor(-1, 0)

; Generate scrollbars - Yes, this is all you need to do!!!!!!!
_GUIScrollbars_Generate($hGUI, 1000, 1000)
GUISetState(@SW_DISABLE, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_RESTORE
            _GUIScrollbars_Restore($hGUI)
        Case $GUI_EVENT_MINIMIZE
            _GUIScrollbars_Minimize($hGUI)
    EndSwitch
WEnd

 

Share this post


Link to post
Share on other sites
TJF

Ok. Better way than ...?

GUIRegisterMsg($WM_MOUSEWHEEL, "")

and

GUIRegisterMsg($WM_MOUSEWHEEL, "_Scrollbars_WM_MOUSEWHEEL")

Share this post


Link to post
Share on other sites
Hernanizero
Posted (edited)

Awsome UDF!!! Congratulations Melba. Can you tell me if there is a Help with all the commands?

Im trying to scroll with a mouse whell after create another contol but i did not works. Even if i put "_GUIScrollbars_Generate($GUI, 1, 1000)" after creates a control like a label

 

Thankyou!!

Edited by Hernanizero

Share this post


Link to post
Share on other sites
Melba23

Hernanizero,

Please post a script which demonstrates the problem - otherwise I cannot help!

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×