Jump to content

Problems with AutoIt Scrollbar UDFs generally


Recommended Posts

I'd first like to thank Jon for creating AutoIt.
Also, thank you to all the developers for the countless hours they selflessly devote to keeping it going.
And lastly thank you to all the people of this forum who offer their guidance to people like me.
 
I've been using AutoIt since 2005 and owe my IT career to all these people.

The "GUIScrollbars_Ex.au3" UDF, developed by Melba23,  has opened the door to many possibilities for me. Melba23 has been one of the best, all time, at contributing to AutoIt and this forum.

For a number of days, I've been trying to resolve what I believe is my logic issue.
I'm creating a script which can be dynamically resized, depending on the size of the controls.
My issue is I can't get the buttons to space evenly at the bottom of the gui.
 
I'm using AutoIt v3.3.16.0 and the "GUIScrollbars_Ex.au3" UDF I downloaded again on April 4th.
 
The below script is only dealing with the number of rows changing.
But once this is resolved, I'd like to apply it to the number of columns changing also.
 
Thank you for the direction anyone may have to offer.

taurus905

; Resizing Gui with Scrollbar Example.au3

#include <WindowsConstants.au3> ; $WS_EX_TOOLWINDOW
#include <GUIScrollbars_Ex.au3> ; _GUIScrollbars_Generate
#include <GUIConstantsEx.au3> ; $GUI_EVENT_CLOSE

HotKeySet("{PAUSE}", "_Increment_Row") ; Increment Row
HotKeySet("{ESC}", "_Exit") ; Exit

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Key_Width = 40
Global $i_Key_Height = 20
Global $i_Row_Increment = 2
Global $i_Rows = 8
Global $i_Cols = 4
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height

; _Create_Schrollbars() ; Create Schrollbars
Global $i_Gui_Titlebar_Height = 27
Global $i_Gui_Boarder = 3
Global $i_Aperture_Width = $i_Key_Width * $i_Cols + _
                            2 * $i_Gui_Boarder
Global $i_Aperture_Height
Global $i_Scrollbar_Size = 17
Global $f_Scrollbar_Horz = 0
Global $f_Scrollbar_Vert = 1

; _Create_Keys() ; Create Keys
Global $s_Key_Name

MsgBox(262208, _ ; $MB_TOPMOST + $MB_ICONINFORMATION
        "Resizing Gui with Scrollbar Example", _
            "Use the 'Pause' key to increment Gui rows" & @CRLF & @CRLF & _
            "and the 'Escape' key to exit script." & @CRLF & @CRLF & _
            "Scroll to end of Gui to see row of keys" & @CRLF & _
            "which shows inconsistent spacing.")

_Increment_Row() ; Increment Row

While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
WEnd

Exit

Func _Increment_Row() ; Increment Row
    GUIDelete($h_Gui)
    $i_Rows += $i_Row_Increment
    $i_Gui_Height = $i_Key_Height * $i_Rows
    _Create_Gui() ; Create Gui
    $i_Aperture_Height = $i_Key_Height * $i_Rows * .5 + _
                            $i_Gui_Titlebar_Height + _
                            $i_Gui_Boarder
    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)
EndFunc ; ==> _Increment_Row

Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("Resizing Gui", _
                        $i_Gui_Width, _
                        $i_Gui_Height, _
                        Default, _
                        Default, _
                        Default, _
                        BitOR($WS_EX_TOOLWINDOW, _
                        $WS_EX_TOPMOST))

    GUISetBkColor(0x000000) ; Black
EndFunc ; ==> _Create_Gui

Func _Create_Schrollbars() ; Create Schrollbars
    WinMove($h_Gui, "", _
            Default, _
            Default, _
            $i_Aperture_Width + $i_Scrollbar_Size, _
            $i_Aperture_Height)

    _GUIScrollbars_Generate($h_Gui, _
                            $i_Gui_Width, _
                            $i_Gui_Height - $i_Scrollbar_Size, _
                            0, _
                            0, _
                            Default, _
                            7) ; Number of lines/chars moved by a single cursor key press - default 0

    _GUIScrollBars_ShowScrollBar($h_Gui, $SB_HORZ, $f_Scrollbar_Horz)
    _GUIScrollBars_ShowScrollBar($h_Gui, $SB_VERT, $f_Scrollbar_Vert)
EndFunc ; ==> _Create_Schrollbars

Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1
            GUICtrlCreateButton($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
            GUICtrlSetBkColor(-1, _
                                0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

Func _Exit() ; Exit
    Exit
EndFunc ; ==> _Exit

 

Edited by Melba23
Amended title given later posts

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

  • Moderators

taurus905,

Thank you for the kind words - much appreciated.

To have correctly-sized scrollbars in a fixed size GUI with a dynamic number of internal controls you need to use _GUIScrollbars_Size, not _GUIScrollbarsEx. The _GUIScrollbars_Size_Example_2 script in the UDF package shows how to use that include file when dealing with a vertical scrollbar - it is a simple matter of duplicating the same logic and adding a new handler to deal with the horizontal case.

Have a go at rewriting your script yourself - you know where I am if you run into problems.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

Thank you for the direction, Melba23.

I appreciate your quick response and you taking the time to analysis my issue.

taurus905

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

Melba23,

I don't believe my issue is with resizing the Gui.
My previous example was created to show how the number of rows impacted how the last row would improperly display  with respect to the length of the window.
 
I think my real issue is my understanding of how the Gui and the Aperture relate.
And also how the other components need to be accounted for, such as, the Titlebar, Scrollbar and Gui Boarders.
 
Here is a simpler script with 12 rows and no incremental examples.
 
Thank you again for taking the time to look at the problem I'm experiencing.
 
taurus905
; 12 Rows of Keys with Scrollbar Example.au3

Opt("MustDeclareVars", 1)

#include <WindowsConstants.au3> ; $WS_EX_TOOLWINDOW
#include <GUIScrollbars_Ex.au3> ; _GUIScrollbars_Generate

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Key_Width = 40
Global $i_Key_Height = 20
Global $i_Rows = 12
Global $i_Cols = 1
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height = $i_Key_Height * $i_Rows

; _Create_Schrollbars() ; Create Schrollbars
Global $i_Gui_Titlebar_Height = 27
Global $i_Gui_Boarder = 3
Global $i_Aperture_Width = $i_Key_Width * $i_Cols + _
                            2 * $i_Gui_Boarder
Global $i_Aperture_Height
Global $i_Scrollbar_Size = 17

; _Create_Keys() ; Create Keys
Global $s_Key_Name

_Create_Gui() ; Create Gui

While 1
        Switch GUIGetMsg()
            Case -3
                ExitLoop
        EndSwitch
WEnd

Exit

Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("12 Rows Gui", _
                        $i_Gui_Width, _
                        $i_Gui_Height, _
                        Default, _
                        Default, _
                        Default, _
                        BitOR($WS_EX_TOOLWINDOW, _
                        $WS_EX_TOPMOST))

    GUISetBkColor(0x000000) ; Black

    $i_Aperture_Height = $i_Key_Height * $i_Rows * .5 + _
                            $i_Gui_Titlebar_Height + _
                            $i_Gui_Boarder

    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)
EndFunc ; ==> _Create_Gui

Func _Create_Schrollbars() ; Create Schrollbars
    WinMove($h_Gui, "", _
            Default, _
            Default, _
            $i_Aperture_Width + $i_Scrollbar_Size, _
            $i_Aperture_Height)

    _GUIScrollbars_Generate($h_Gui, _
                            $i_Gui_Width, _
                            $i_Gui_Height - $i_Scrollbar_Size, _
                            0, _
                            0, _
                            Default, _
                            7) ; Number of lines/chars moved by a single cursor key press - default 0

    _GUIScrollBars_ShowScrollBar($h_Gui, $SB_VERT, 1)
EndFunc ; ==> _Create_Schrollbars

Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1
            GUICtrlCreateButton($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
            GUICtrlSetBkColor(-1, _
                                0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

 

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

Here are two screenshots of the Gui to show how the Keys display above and below the fold:

1697647618_First6Keys.png.cdaab41a9788012ffb15b03ee9622c0f.png1771378104_Second6Keys.png.432a0e5ac9c216aff4c3cce2a7bd7e5f.png

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

Hi taurus905
Following Melba23's advice, I tried _GUIScrollbars_Size on a lighter version of your 1st script. Results are accurate until a hundred buttons are displayed. After that...

; Resizing Gui with Scrollbar Example.au3

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include "GUIScrollbars_Size.au3"

Opt("MustDeclareVars", 1)

HotKeySet("{PAUSE}", "_Increment_Row") ; Increment Row
HotKeySet("{ESC}", "_Exit") ; Exit

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Key_Width = 40
Global $i_Key_Height = 32
Global $i_Row_Increment = 2
Global $i_Rows = 10
Global $i_Cols = 4
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height

; _Create_Schrollbars() ; Create Schrollbars
Global $i_Scrollbar_Size = 17

; _Create_Keys() ; Create Keys
Global $s_Key_Name

MsgBox(262208, _ ; $MB_TOPMOST + $MB_ICONINFORMATION
        "Resizing Gui with Scrollbar Example", _
            "Use the 'Pause' key to increment Gui rows" & @CRLF & @CRLF & _
            "and the 'Escape' key to exit script." & @CRLF & @CRLF & _
            "Scroll to end of Gui to see row of keys" & @CRLF & _
            "which shows (in)consistent spacing.")

GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")

_Increment_Row() ; Increment Row

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $GUI_EVENT_RESTORE
            _GUIScrollbars_Restore($h_GUI, True, False)
    EndSwitch
WEnd

;==============================================
Func _Increment_Row() ; Increment Row
    GUIDelete($h_Gui)
    $i_Rows += $i_Row_Increment
    $i_Gui_Height = $i_Key_Height * $i_Rows
    _Create_Gui() ; Create Gui
    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)
EndFunc ; ==> _Increment_Row

;==============================================
Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("Resizing Gui", _
                        $i_Gui_Width + $i_Scrollbar_Size, _
                        $i_Gui_Height / 2, _
                        Default, _
                        Default, _
                        Default, _
                        $WS_EX_TOPMOST)

    GUISetBkColor(0x000000) ; Black
EndFunc ; ==> _Create_Gui

;==============================================
Func _Create_Schrollbars() ; Create Schrollbars

    Local $aRet = _GUIScrollbars_Size(0, $i_Gui_Height - 9, $i_Gui_Width + $i_Scrollbar_Size, $i_Gui_Height / 2)
    _GUIScrollBars_Init($h_GUI)
    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, True)
    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, False)
    _GUIScrollBars_SetScrollInfoPage($h_GUI, $SB_VERT, $aRet[2])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_VERT, $aRet[3])

EndFunc ; ==> _Create_Schrollbars

;==============================================
Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1
            GUICtrlCreateButton($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
            GUICtrlSetBkColor(-1, _
                                0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

;==============================================
Func _Exit() ; Exit
    Exit
EndFunc ; ==> _Exit

;==============================================
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

141179597_M23sscrollbars.png.1aaae3f7912c9b9056e017ecc00e5939.png

Hope it helps :)

Edit: do not use the script above. There are more robust scripts in the posts below.

Edited by pixelsearch
typo
Link to comment
Share on other sites

  • Moderators

taurus905,

Quote

I think my real issue is my understanding of how the Gui and the Aperture relate

The "aperture" is the size of the visible GUI in which the scrollbars are placed - the "GUI" is the underlying area which holds the controls and is scrolled into view within the aperture, this is obviously larger than the aperture or there would be no need to scroll! 

Quote

how the other components need to be accounted for, such as, the Titlebar, Scrollbar and Gui Boarders

You can ignore them - the scrollbars only deal with the internal "client" area.

Here are 2 scripts which I hope will give you a clear idea of how the 2 UDFs work. Firstly a GUIScrollbars_Ex script using hard-coded row/column values to show how easy it is to get the  scrollbars sized:

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

#include "GUIScrollbars_Ex.au3"

Global $i_Key_Width = 40
Global $i_Key_Height = 20
Global $i_Rows = 12
Global $i_Cols = 4

; Calculate the size of the full GUI to be scrolled
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height = $i_Key_Height * $i_Rows

; Create the GUI with the size of the aperture to be used
Global $hGUI = GUICreate("Test", 200, 200)

; Next create the keys in the full sized GUI
_Create_Keys()

GUISetState()

; Now generate the scrollbars using the size of the underlying GUI to be scrolled
_GUIScrollbars_Generate($hGUI, $i_Gui_Width, $i_Gui_Height)
; You could also use the "Tight" parameter to minimize the margins if desired, but I would recommend not doing so

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    ; The latest version of the _Ex UDF now uses this function rather then the _MINIMIZE/_RESTORE event calls
    _GUIScrollbars_EventMonitor()

WEnd

Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1
            GUICtrlCreateButton($s_Key_Name, ($col) * $i_Key_Width, ($row) * $i_Key_Height, $i_Key_Width, $i_Key_Height)
            ;GUICtrlSetBkColor(-1, 0xFFFFFF) ; White ; Very bad idea <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            GUICtrlSetFont(-1, Default, 900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

Play with the $i_Rows and $i_Cols values between runs to see how the UDF copes with the different values.

Now a GUIScrollbars_Size script to show how you can deal with changing the number of controls in the underlying GUI during execution:

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

#include "GUIScrollbars_Size.au3"

HotKeySet("^+R", "_Increase_Rows")

Global $i_Key_Width = 40
Global $i_Key_Height = 20
Global $i_Rows = 12
Global $i_Cols = 4

; Calculate the size of the full GUI to be scrolled
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height = $i_Key_Height * $i_Rows

; Create the GUI with the size of the aperture to be used
Global $hGUI = GUICreate("Test", 200, 200)

GUISetState()

If $i_Gui_Height <= 200 Then
    $i_Gui_Height = 0
EndIf

; Only interested in vertical scrollbar at present
$aRet = _GUIScrollbars_Size(0, $i_Gui_Height, 200, 200)
; Parameters:   0             - No horizontal scroll needed
;               $i_Gui_Height - Vertical size of underlying GUI
;               200           - Width of aperture GUI
;               200           - Height of aperture GUI

; Register the vertical handler
GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")

; Create and set parameters for the vertical scrollbar
_GUIScrollBars_Init($hGUI)
_GUIScrollBars_ShowScrollBar($hGUI, $SB_VERT, True)
_GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
_GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])

; Hide horizontal scrollbar
_GUIScrollBars_ShowScrollBar($hGUI, $SB_HORZ, False)

; Create keys
_Create_Keys()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_RESTORE ; Still needed if you use the _Size UDF
            _GUIScrollbars_Restore($hGUI, True, False)
    EndSwitch

WEnd

Func _Increase_Rows()

    ; Save current final row
    Local $iCurrRows = $i_Rows
    ; Add rows
    $i_Rows += 4
    ; create the new keys
    _Create_Keys($iCurrRows)
    ; Calculate the new height
    $i_Gui_Height = $i_Key_Height * $i_Rows
    ; Use the UDF to get the new scrollbar parameters
    $aRet = _GUIScrollbars_Size(0, $i_Gui_Height, 200, 200)
    ; And set them
    _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
    _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])

EndFunc

Func _Create_Keys($iCurrRows = 0) ; Create Keys
    For $row = $iCurrRows To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1
            GUICtrlCreateButton($s_Key_Name, ($col) * $i_Key_Width, ($row) * $i_Key_Height, $i_Key_Width, $i_Key_Height)
            ;GUICtrlSetBkColor(-1, 0xFFFFFF) ; White ; Very bad idea <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            GUICtrlSetFont(-1, Default, 900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

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

Each time the number of controls is increased, the UDF calculates the correct parameters to use when resetting the scrollbars to ensure that they are correctly sized to match the new height of the underlying GUI.

I hope this clarifies how to use the 2 UDFs - do not hesitate to ask if you need further explanation.

M23

P.S. And as mentioned in the comments - DO NOT colour buttons - it leads to all sorts of problems as explained here.

Edit: And here is an example which is dynamic in both directions:

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

#include <WinAPISys.au3>

#include "GUIScrollbars_Size.au3"

HotKeySet("^+R", "_Increase_Rows")
HotKeySet("^+C", "_Increase_Cols")

; Get size of scrollbars
Global $iScroll_Width = _WinAPI_GetSystemMetrics(2) ; Width of VScrollbar:  SM_CXVSCROLL
Global $iScroll_Height = _WinAPI_GetSystemMetrics(3) ; Height of HScrollbar: SM_CYHSCROLL

; Set key parameters
Global $i_Key_Width = 40
Global $i_Key_Height = 20
Global $i_Rows = 12
Global $i_Cols = 8

; Calculate the size of the full GUI to be scrolled
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height = $i_Key_Height * $i_Rows

; Create the GUI with the size of the aperture to be used
Global $hGUI = GUICreate("Test", 200, 200)

GUISetState()

$aRet = _GUIScrollbars_Size($i_Gui_Width, $i_Gui_Height, 200, 200)
; Parameters:   $i_Gui_Width  - Width of underlying GUI
;               $i_Gui_Height - Vertical size of underlying GUI
;               200           - Width of aperture GUI
;               200           - Height of aperture GUI

; Register the handlers
GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")
GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")

; Create scrollbars
_GUIScrollBars_Init($hGUI)
;Show and set parameters for horizontal scrollbar
_GUIScrollBars_ShowScrollBar($hGUI, $SB_HORZ, True)
_GUIScrollBars_SetScrollInfoPage($hGUI, $SB_HORZ, $aRet[0])
_GUIScrollBars_SetScrollInfoMax($hGUI, $SB_HORZ, $aRet[1])
; And then for vertical
_GUIScrollBars_ShowScrollBar($hGUI, $SB_VERT, True)
_GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
_GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])

; Create keys
_Create_Keys()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_RESTORE ; Still needed if you use the _Size UDF
            _GUIScrollbars_Restore($hGUI, True, False)
    EndSwitch

WEnd

Func _Increase_Cols()

    ; Save scrollbar positions and set to 0
    Local $iHorz = _GUIScrollBars_GetScrollInfoPos($hGUI, $SB_HORZ)
    Local $iVert = _GUIScrollBars_GetScrollInfoPos($hGUI, $SB_VERT)
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_HORZ, 0)
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_VERT, 0)
    ; Save current final col
    Local $iCurrCols = $i_Cols
    ; Add rows
    $i_Cols += 4
    ; Create the new keys
    _Create_Keys(0, $iCurrCols)
    ; Calculate the new height
    $i_Gui_Width = $i_Key_Width * $i_Cols
    ; Use the UDF to get the new scrollbar parameters
    $aRet = _GUIScrollbars_Size($i_Gui_Width + $iScroll_Width, 0, 200, 200)
    ; And set them
    _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_HORZ, $aRet[0])
    _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_HORZ, $aRet[1])
    ; Reset positions
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_HORZ, $iHorz)
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_VERT, $iVert)

EndFunc

Func _Increase_Rows()

    ; Save scrollbar positions and set to 0
    Local $iHorz = _GUIScrollBars_GetScrollInfoPos($hGUI, $SB_HORZ)
    Local $iVert = _GUIScrollBars_GetScrollInfoPos($hGUI, $SB_VERT)
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_HORZ, 0)
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_VERT, 0)
    ; Save current final row
    Local $iCurrRows = $i_Rows
    ; Add rows
    $i_Rows += 4
    ; create the new keys
    _Create_Keys($iCurrRows)
    ; Calculate the new height
    $i_Gui_Height = $i_Key_Height * $i_Rows
    ; Use the UDF to get the new scrollbar parameters
    $aRet = _GUIScrollbars_Size(0, $i_Gui_Height + $iScroll_Height, 200, 200)
    ; And set them
    _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
    _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])
    ; Reset positions
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_HORZ, $iHorz)
    _GUIScrollBars_SetScrollInfoPos($hGUI, $SB_VERT, $iVert)

EndFunc

Func _Create_Keys($iCurrRows = 0, $iCurrCols = 0) ; Create Keys
    For $row = $iCurrRows To $i_Rows - 1
        For $col = $iCurrCols To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1
            GUICtrlCreateButton($s_Key_Name, ($col) * $i_Key_Width, ($row) * $i_Key_Height, $i_Key_Width, $i_Key_Height)
            GUICtrlSetFont(-1, Default, 900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

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

    #forceref $Msg, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
    Local $iIndex = -1, $xChar, $xPos
    Local $Page, $Pos, $TrackPos

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

    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    $xPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $xPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    Switch $nScrollCode
        Case $SB_LINELEFT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
        Case $SB_LINERIGHT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
        Case $SB_PAGELEFT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
        Case $SB_PAGERIGHT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
        Case $SB_THUMBTRACK
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

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

    $Pos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($Pos <> $xPos) Then _GUIScrollBars_ScrollWindow($hWnd, $xChar * ($xPos - $Pos), 0)

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_HSCROLL

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

 

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

15 hours ago, pixelsearch said:

Hi taurus905
Following Melba23's advice, I tried _GUIScrollbars_Size on a lighter version of your 1st script. Results are accurate until a hundred buttons are displayed. After that...

 

Hello pixelsearch,

Thank you for taking the time to help me understand how to use Melba23's UDF. People like you are a large part of the reason so many people LOVE AutoIt.

I wanted to verify you are seeing the same output as I do when running your edited version of my original script. This is what I see. And each iteration after creates an ever expanding black space below the last row.

 

AutoIt3_4dMIvnV5ct.png

AutoIt3_q4GA70fUzz.png

AutoIt3_RregAThHhQ.png

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

@Melba23 great 3 examples, they'll definitely help users dealing with custom Scrollbars :)

@taurus905 thanks for the kind words.

On 4/13/2022 at 11:18 PM, taurus905 said:

I wanted to verify you are seeing the same output as I do when running your edited version of my original script. This is what I see. And each iteration after creates an ever expanding black space below the last row.

Yes I do see the same bad output, that's why I wrote "it worked fine with approx. 100 buttons, after that..." .  I can amend the code with some constants to work better... though it's not a good solution, because it will display everything correctly but we won't know what caused the issues. Only M23 or someone having knowledge in scrollbars (that's not me) could explain the issues encountered until then.

If I understood you correctly, what you really want is to have the buttons match perfectly the lower edge of the GUI, without any gap or any button not showing completely. Here is a pic showing what didn't work (3 GUI's on the left) and how it can be amended to display correctly (GUI on the right) :

1497549911_Scrollbarsapprox.png.11af5212dea105ed85e47e4c23eebc08.png

The 3 GUI's on the left show the issue encountered in the edited script of the previous post :
* Everything works fine until 26 rows are displayed (1st GUI)
* An incredible horizontal scrollbar appears (God only knows why !) when 2 more rows are added (2nd GUI)
* That same horizontal scrollbar disappears immediately after 2 more rows are added... but now, a gap starts to show between the last row and the bottom edge (3rd GUI). And that gap will have its size increasing, as shown on your pics in your previous post.

To solve all this, I added some constants to the script below, but it's not a good solution. Also, I replaced the buttons with labels (minor change in this context). The display is now correct : see how the 4th GUI on the right shows 44 full rows in the pic above ... but I don't like at all this patch based on constants. It would be great if anyone  could explain why the horizontal scrollbar appeared mysteriously in the 2nd GUI !

; Resizing Gui with Scrollbar Example.au3

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include "GUIScrollbars_Size.au3"

Opt("MustDeclareVars", 1)

HotKeySet("{PAUSE}", "_Increment_Row") ; Increment Row
HotKeySet("{ESC}", "_Exit") ; Exit

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Key_Width = 40
Global $i_Key_Height = 32
Global $i_Row_Increment = 2
Global $i_Rows = 10
Global $i_Cols = 4
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height

; _Create_Schrollbars() ; Create Schrollbars
Global $i_Scrollbar_Size = 17

; _Create_Keys() ; Create Keys
Global $s_Key_Name

MsgBox(262208, _ ; $MB_TOPMOST + $MB_ICONINFORMATION
        "Resizing Gui with Scrollbar Example", _
            "Use the 'Pause' key to increment Gui rows" & @CRLF & @CRLF & _
            "and the 'Escape' key to exit script." & @CRLF & @CRLF & _
            "Scroll to end of Gui to see row of keys" & @CRLF & _
            "which shows (in)consistent spacing.")

GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")

_Increment_Row() ; Increment Row

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $GUI_EVENT_RESTORE
            _GUIScrollbars_Restore($h_GUI, True, False)
    EndSwitch
WEnd

;==============================================
Func _Increment_Row() ; Increment Row
    GUIDelete($h_Gui)
    $i_Rows += $i_Row_Increment
    $i_Gui_Height = $i_Key_Height * $i_Rows
    _Create_Gui() ; Create Gui
    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)
EndFunc ; ==> _Increment_Row

;==============================================
Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("Resizing Gui", _
                        $i_Gui_Width + $i_Scrollbar_Size, _
                        $i_Gui_Height / 2, _
                        Default, _
                        Default, _
                        Default, _
                        $WS_EX_TOPMOST)
EndFunc ; ==> _Create_Gui

;==============================================
Func _Create_Schrollbars() ; Create Schrollbars

    Local $aRet = _GUIScrollbars_Size(0, $i_Gui_Height -9, $i_Gui_Width + $i_Scrollbar_Size, $i_Gui_Height / 2)
    If $aRet[2] >= 30 Then ; or an increasing gap starts to appear at the bottom of the GUI
        Local $iInc = ($aRet[2] - 28) / 2
        $aRet[2] -= 2 * $iInc
        $aRet[3] -= 2 * $iInc
    EndIf
    _GUIScrollBars_Init($h_GUI)
    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, True)
    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, False)
    _GUIScrollBars_SetScrollInfoPage($h_GUI, $SB_VERT, $aRet[2])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_VERT, $aRet[3])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_HORZ, 0) ; or an horiz scrollbar appears when $aRet[2] = 28 !
EndFunc ; ==> _Create_Schrollbars

;==============================================
Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1

            GUICtrlCreateLabel($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height, _
                                BitOr($SS_CENTERIMAGE, $SS_CENTER, $SS_SUNKEN), _
                                $GUI_WS_EX_PARENTDRAG)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
             GUICtrlSetBkColor(-1, _
                                 0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

;==============================================
Func _Exit() ; Exit
    Exit
EndFunc ; ==> _Exit

;==============================================
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

Sorry M23 for all these big pics in your thread. If you think these last posts should be placed in another thread, that's fine too.

Edit: do not use the script above. There are more robust scripts in the posts below.

Edited by pixelsearch
Link to comment
Share on other sites

Thank you, Melba23 for your detailed explanation and three example scripts.

I especially appreciate the simplicity of the first script and will build on it after studying the other two as well as the internal workings of your UDF.

I remember one of my first posts in 2005 concerned the coloring of buttons. The temporary work-around was to use labels, as pixelsearch just referred to. Then later, I thought this issue was addressed and I went back to using buttons. Thank you for reminding me this may cause problems. I will keep that in mind.

I'm grateful for all the time you've spent helping me.

taurus905

P.S. I also apologize for all the screenshots in your thread. Please edit them as you see fit. 

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

30 minutes ago, pixelsearch said:

Yes I do see the same bad output, that's why I wrote "it worked fine with approx. 100 buttons, after that..." .

@pixelsearch I apologize for mis-reading your post. I read "100 buttons", but my mind was thinking "100 rows". If you configure the Gui from 4 columns to just 1, you will see the same behavior with only  28 buttons. Therefore, it is a function of the number of rows which causes the unexpected horizontal scrollbar.

You've also described the issue precisely, pertaining to how at 30 rows the horizontal scrollbar no longer shows, but a ever increasing gap displays between the last row and the bottom edge of the Gui.

Before I posted this issue a few days ago, I tried constructing some type of algorithm to inject a correct factor in order to get the desired output. But as you stated, it's not a good solution.

I believe both you and Melba23 see and understand the issue as I do. That alone makes me feel a solution will be found.

I am determined to have total control of my scrollbars. And by considering everyone's input, I'm sure this will happen.

taurus905  

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

  • Moderators

taurus905 & pixelsearch,

As is explained in the tutorial in the first post of this thread (you did read it?) scrollbars - at least to my knowledge of their implementation in AutoIt - work on line height and average character width. Because of this, it is almost impossible to get the scroll to exactly fit an underlying GUI of arbitrary size - and is the reason I introduced the "tight" parameters in the _Generate call, the effects of which is shown in the graphic within the tutorial. So "total control" is probably out of the question and you are going to have to accept a degree of either positive or negative "margin" at the bottom and right of any given scrolled GUI.

Of course if anyone wants to prove me wrong, I would be delighted.....

M23

 

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

On 4/14/2022 at 10:22 AM, Melba23 said:

you did read it?

I sure did read it before starting all this, at least twice :D
That's the reason why I did set $i_Key_Height to 32 in the script above (32 being 2*16, and 16 is the line height on my computer)

I think the key for trying to have no vertical gap and controls fully visible is to use multiples of line height, that means buttons/labels having a height of 16 or 32 (on my computer)

* First I noticed that value of 16 in your function _GUIScrollbars_Size()

; Determine GUI text size
$aRet = _GSB_Size_Text($hWnd)
...
$iX_Char = $aRet[0] ; 7  on my computer
$iY_Char = $aRet[1] ; 16  "  "     "

* It seems possible to retrieve that line height with a short code placed at the beginning of the script, something like this :

; Get line height
Global $iLineHeight = _GSB_Size_Text(GUICreate(""))[1]
GUIDelete()
; ConsoleWrite($iLineHeight & @crlf) ; 16 on my computer

* Finally (and this should also help to solve taurus905 issue) 16 is also found in a global array declared in... GuiScrollBars.au3 :

Global $__g_aSB_WindowInfo[1][8]
; 0 = hwnd;1 = xClientMax;2 cxChar;3 = cyChar;4 cxClient;5 = cyClient,6 = iHMax;7 = iVMax

This is the content of this array during taurus905's script (which deletes the GUI and recreates it each time new rows are added, this explains why there are several rows in the array) :

1043455394_ScrollbarWindowInfo.png.cf41213d08c5623c9c8df88b48225b8d.png

7 & 16 in Col 2 & 3, I guess these values depend on the OS and may vary from a computer to the other.

Now let's focus on that constant of 27 found in Col 7. That's why we are stuck with a phantom horizontal scrollbar appearing when $aRet[2] = 28, then a growing gap at the bottom of the Gui, because of the following line found in _GUIScrollBars_Init() :

If $iMaxV = -1 Then $__g_aSB_WindowInfo[$iIndex][7] = 27

If we increase that value, not by changing directly 27 in the function, but by passing a 3rd parameter when calling _GUIScrollBars_Init(), then there will be no phantom horizontal scrollbar and no gap at the bottom of the GUI :

2100246979_Scrollbarsaccurate.png.40a54d8d24056e062f1f2a2d30835621.png

The code that led to the pic above :

; Resizing Gui with Vertical Scrollbar Example.au3

#include <Array.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPISys.au3>

#include "GUIScrollbars_Size.au3"

Opt("MustDeclareVars", 1)

HotKeySet("{PAUSE}", "_Increment") ; Increment
HotKeySet("{ESC}", "_Exit") ; Exit

; Get 1 character height & width (before creating GUI, as it will be used to calculate controls size)
Global $aCharSize = _GSB_Size_Text(GUICreate("")) ; M23's internal function in GUIScrollbars_Size.au3
GUIDelete()
Global $iCharWidth = $aCharSize[0], $iCharHeight = $aCharSize[1]
; ConsoleWrite($iCharWidth & "   " & $iCharHeight & @crlf) ; 7 & 16 on my PC

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Increment = 2
Global $i_Rows = 24
Global $i_Cols = 4
Global $i_Key_Width = $iCharWidth * 6 ; 42 on my PC (7 * 6)
Global $i_Key_Height = $iCharHeight * 2 ; 32 on my PC (16 * 2)
Global $i_Gui_Width = $i_Key_Width * $i_Cols
Global $i_Gui_Height
Global $nV_Pos, $iIncMini = 0

; _Create_Schrollbars() ; Create Schrollbars
Global $iScroll_Width = _WinAPI_GetSystemMetrics(2) ; Width of VScrollbar:  SM_CXVSCROLL
Global $iScroll_Height = _WinAPI_GetSystemMetrics(3) ; Height of HScrollbar: SM_CYHSCROLL
; ConsoleWrite($iScroll_Width & "   " & $iScroll_Height & @crlf) ; 17 & 17 on my PC

; _Create_Keys() ; Create Keys
Global $s_Key_Name

MsgBox(262208, _ ; $MB_TOPMOST + $MB_ICONINFORMATION
        "Resizing Gui with Vertical Scrollbar Example", _
            "Use the 'Pause' key to increment Gui rows" & @CRLF & @CRLF & _
            "and the 'Escape' key to exit script." & @CRLF & @CRLF & _
            "Scroll to end of Gui to see row of keys" & @CRLF & _
            "which shows consistent spacing.")

GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")

_Increment() ; Increment

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch

    If BitAND(WinGetState($h_GUI), $WIN_STATE_MINIMIZED) Then ; Minimize button, Win-D, hide all
        $iIncMini += 1
        If $iIncMini = 1 Then
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, False)
            $nV_Pos = _GUIScrollBars_GetScrollPos($h_GUI, $SB_VERT)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_VERT, 0)
        EndIf
    Else ; not Minimized
        If $iIncMini Then
            $iIncMini = 0
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, True)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_VERT, $nV_Pos)
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, False) ; keep that line
        EndIf
    EndIf
WEnd

;========================================================
Func _Increment() ; Increment
    GUIDelete($h_Gui)

    ; As the script deletes the GUI for each increment, no need to keep useless rows...
    ; ... in the GLOBAL array $__g_aSB_WindowInfo[][] declared in GuiScrollBars.au3
    ; But it's also a good idea to keep the "useless" rows to check the changed values.
    ; Global $__g_aSB_WindowInfo[1][8] ; reset, exactly as found in GuiScrollBars.au3
    ; _ArrayDisplay($__g_aSB_WindowInfo, "$__g_aSB_WindowInfo", Default, $ARRAYDISPLAY_NOROW)

    $i_Rows += $i_Increment
    $i_Gui_Height = $i_Key_Height * $i_Rows

    _Create_Gui() ; Create Gui
    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)

EndFunc ; ==> _Increment

;========================================================
Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("Resizing Gui", _
                        $i_Gui_Width + $iScroll_Width, _
                        $i_Gui_Height / 2, _
                        Default, _
                        Default, _
                        Default, _
                        $WS_EX_TOPMOST)
EndFunc ; ==> _Create_Gui

;========================================================
Func _Create_Schrollbars() ; Create Schrollbars

    Local $aRet = _GUIScrollbars_Size(0, $i_Gui_Height - $iScroll_Height / 2, _
        $i_Gui_Width + $iScroll_Width, $i_Gui_Height / 2)
    ; ConsoleWrite("$aRet[2] = " & $aRet[2] & "   $aRet[3] = " & $aRet[3] & @crlf)

;~  _GUIScrollBars_Init($h_GUI) ; phantom scrollbar + gap when no 2nd / 3rd param.
    _GUIScrollBars_Init($h_GUI, -1, 100) ; 3rd parameter to bypass the constant of 27

    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, True)
    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, False)
    _GUIScrollBars_SetScrollInfoPage($h_GUI, $SB_VERT, $aRet[2])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_VERT, $aRet[3])
EndFunc ; ==> _Create_Schrollbars

;========================================================
Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1

            GUICtrlCreateLabel($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height, _
                                BitOr($SS_CENTERIMAGE, $SS_CENTER, $SS_SUNKEN), _
                                $GUI_WS_EX_PARENTDRAG)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
             GUICtrlSetBkColor(-1, _
                                 0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

;========================================================
Func _Exit() ; Exit
    Exit
EndFunc ; ==> _Exit

;========================================================
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

I was lucky to find that global array $__g_aSB_WindowInfo[1][8] and its constant of 27, even if it took a long time. I hope the explanations above are correct and it may help @taurus905 to achieve his goal :)

Edited by pixelsearch
While... Wend loop more robust, taking care of Minimize button, Win-D, hide all
Link to comment
Share on other sites

3 hours ago, pixelsearch said:

I was lucky to find that global array $__g_aSB_WindowInfo[1][8] and its constant of 27, even if it took a long time. I hope the explanations above are correct and it may help @taurus905 to achieve his goal :)

@pixelsearchWow! Very good detective work, my friend.

You solved this much quicker than I ever would have, if ever.

I at least owe you a pint, or a coffee if you'd prefer. :D

taurus905

"Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs

Link to comment
Share on other sites

On 4/14/2022 at 12:35 AM, taurus905 said:

I at least owe you a pint, or a coffee if you'd prefer. :D

Thank you, let's have both :)

Ok, my preceding post tested a vertical scrollbar and showed a possible issue in the function _GUIScrollBars_Init() found in GuiScrollBars.au3, because of a constant = 27, when the function is called with only 1 argument :

Func _GUIScrollBars_Init($hWnd, $iMaxH = -1, $iMaxV = -1)
    ...
    If $iMaxV = -1 Then $__g_aSB_WindowInfo[$iIndex][7] = 27
    ...
EndFunc

Now let's start some tests with an horizontal scrollbar, which will show a similar issue :

893328833_horizscrollbarbad.thumb.png.3fd0fcb293a3b787b3ebf7a5216ba233.png

The code corresponding to the pic above will be found below. Meanwhile :
* 1st & 2nd gui are correct : no vertical phantom scrollbar, no gap.
* 3rd gui shows a non-draggable vertical phantom scrollbar.
* 4th gui shows a gap at the right, which would increase indefinitely when you add columns.

Starting with 3rd gui, the issue appears because of the following line :

Func _GUIScrollBars_Init($hWnd, $iMaxH = -1, $iMaxV = -1)
    ...
    If $iMaxH = -1 Then $__g_aSB_WindowInfo[$iIndex][1] = 48 * $iXAmount + 12 * $iUpperX
    ...
EndFunc

Do you notice this value of 462 in Col1 of all preceding ArrayDisplay's ?
This is the value of $__g_aSB_WindowInfo[$iIndex][1] on my computer. As soon as the value in Col4 (cxClient) becomes superior to 462, then a vertical non-draggable phantom scrollbar & gap will appear.

A possible solution is to increase this value of 462 when calling _GUIScrollBars_Init(), like this :

; _GUIScrollBars_Init($h_GUI) ; phantom scrollbar + gap when no 2nd / 3rd param.
_GUIScrollBars_Init($h_GUI, 1500) ; 2nd parameter passed to avoid phantom scrollbar + gap

Then everything comes back to normal :

567012317_horizscrollbargood.thumb.png.4a1c1083adee1430c3b96b7eb9e59a95.png

Code corresponding to these pics :

; Resizing Gui with Horizontal Scrollbar Example.au3

#include <Array.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPISys.au3>

#include "GUIScrollbars_Size.au3"

Opt("MustDeclareVars", 1)

HotKeySet("{PAUSE}", "_Increment") ; Increment
HotKeySet("{ESC}", "_Exit") ; Exit

; Get 1 character height & width (before creating GUI, as it will be used to calculate controls size)
Global $aCharSize = _GSB_Size_Text(GUICreate("")) ; M23's internal function in GUIScrollbars_Size.au3
GUIDelete()
Global $iCharWidth = $aCharSize[0], $iCharHeight = $aCharSize[1]
; ConsoleWrite($iCharWidth & "   " & $iCharHeight & @crlf) ; 7 & 16 on my PC

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Increment = 2
Global $i_Rows = 6
Global $i_Cols = 8
Global $i_Key_Width = $iCharWidth * 10 ; 70 on my PC (7 * 10)
Global $i_Key_Height = $iCharHeight * 1 ; 16 on my PC (16 * 1)
Global $i_Gui_Width
Global $i_Gui_Height = $i_Key_Height * $i_Rows
Global $nH_Pos, $iIncMini = 0

; _Create_Schrollbars() ; Create Schrollbars
Global $iScroll_Width = _WinAPI_GetSystemMetrics(2) ; Width of VScrollbar:  SM_CXVSCROLL
Global $iScroll_Height = _WinAPI_GetSystemMetrics(3) ; Height of HScrollbar: SM_CYHSCROLL
; ConsoleWrite($iScroll_Width & "   " & $iScroll_Height & @crlf) ; 17 & 17 on my PC

; _Create_Keys() ; Create Keys
Global $s_Key_Name

MsgBox(262208, _ ; $MB_TOPMOST + $MB_ICONINFORMATION
        "Resizing Gui with Horizontal Scrollbar Example", _
            "Use the 'Pause' key to increment Gui cols" & @CRLF & @CRLF & _
            "and the 'Escape' key to exit script." & @CRLF & @CRLF & _
            "Scroll to end of Gui to see cols of keys" & @CRLF & _
            "which shows consistent spacing.")

GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")

_Increment() ; Increment

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch

    If BitAND(WinGetState($h_GUI), $WIN_STATE_MINIMIZED) Then ; Minimize button, Win-D, hide all
        $iIncMini += 1
        If $iIncMini = 1 Then
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, False)
            $nH_Pos = _GUIScrollBars_GetScrollPos($h_GUI, $SB_HORZ)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_HORZ, 0)
        EndIf
    Else ; not Minimized
        If $iIncMini Then
            $iIncMini = 0
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, True)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_HORZ, $nH_Pos)
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, False) ; keep that line
        EndIf
    EndIf
WEnd

;==============================================
Func _Increment() ; Increment
    GUIDelete($h_Gui)

    ; As the script deletes the GUI for each increment, no need to keep useless rows...
    ; ... in the GLOBAL array $__g_aSB_WindowInfo[][] declared in GuiScrollBars.au3
    ; But it's also a good idea to keep the "useless" rows to check the changed values.
    ; Global $__g_aSB_WindowInfo[1][8] ; reset, exactly as found in GuiScrollBars.au3
    ; _ArrayDisplay($__g_aSB_WindowInfo, "$__g_aSB_WindowInfo", Default, $ARRAYDISPLAY_NOROW)

    $i_Cols += $i_Increment
    $i_Gui_Width = $i_Key_Width * $i_Cols

    _Create_Gui() ; Create Gui
    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)

EndFunc ; ==> _Increment

;========================================================
Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("Resizing Gui", _
                        $i_Gui_Width / 2, _
                        $i_Gui_Height + $iScroll_Height, _
                        Default, _
                        Default, _
                        Default, _
                        $WS_EX_TOPMOST)
EndFunc ; ==> _Create_Gui

;========================================================
Func _Create_Schrollbars() ; Create Schrollbars

    Local $aRet = _GUIScrollbars_Size($i_Gui_Width - $iScroll_Width / 2, 0, _
        $i_Gui_Width / 2, $i_Gui_Height + $iScroll_Height)
    ; ConsoleWrite("$aRet[0] = " & $aRet[0] & "   $aRet[1] = " & $aRet[1] & @crlf)

;~      _GUIScrollBars_Init($h_GUI)   ; phantom scrollbar + gap when no 2nd / 3rd param.
    _GUIScrollBars_Init($h_GUI, 1500) ; 2nd parameter changed to avoid phantom scrollbar + gap

    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, False)
    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, True)
    _GUIScrollBars_SetScrollInfoPage($h_GUI, $SB_HORZ, $aRet[0])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_HORZ, $aRet[1] + 1) ; (+ 1 after test)
EndFunc ; ==> _Create_Schrollbars

;========================================================
Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1

            GUICtrlCreateLabel($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height, _
                                BitOr($SS_CENTERIMAGE, $SS_CENTER, $SS_SUNKEN), _
                                $GUI_WS_EX_PARENTDRAG)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
             GUICtrlSetBkColor(-1, _
                                 0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

;========================================================
Func _Exit() ; Exit
    Exit
EndFunc ; ==> _Exit

;========================================================
Func _Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)

    #forceref $Msg, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
    Local $iIndex = -1, $xChar, $xPos
    Local $Page, $Pos, $TrackPos

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

    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    $xPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $xPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    Switch $nScrollCode
        Case $SB_LINELEFT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
        Case $SB_LINERIGHT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
        Case $SB_PAGELEFT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
        Case $SB_PAGERIGHT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
        Case $SB_THUMBTRACK
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

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

    $Pos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($Pos <> $xPos) Then _GUIScrollBars_ScrollWindow($hWnd, $xChar * ($xPos - $Pos), 0)

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_HSCROLL

I'll try to add in a further post some tests results when both scrollbars are present.

Edited by pixelsearch
While... Wend loop more robust, taking care of Minimize button, Win-D, hide all
Link to comment
Share on other sites

  • Melba23 changed the title to Problems with AutoIt Scrollbar UDFs generally

@taurus905 You'll find below the code that manages 2 scrollbars :

; Resizing Gui with both Scrollbars Example.au3

#include <Array.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPISys.au3>

#include "GUIScrollbars_Size.au3"

Opt("MustDeclareVars", 1)

HotKeySet("{PAUSE}", "_Increment") ; Increment
HotKeySet("{ESC}", "_Exit") ; Exit

; Get 1 character height & width (before creating GUI, as it will be used to calculate controls size)
Global $aCharSize = _GSB_Size_Text(GUICreate("")) ; M23's internal function in GUIScrollbars_Size.au3
GUIDelete()
Global $iCharWidth = $aCharSize[0], $iCharHeight = $aCharSize[1]
; ConsoleWrite($iCharWidth & "   " & $iCharHeight & @crlf) ; 7 & 16 on my PC

; _Create_Gui() ; Create Gui
Global $h_Gui
Global $i_Increment = 2
Global $i_Rows = 8
Global $i_Cols = 8
Global $i_Key_Width = $iCharWidth * 6 ; 42 on my PC (7 * 6)
Global $i_Key_Height = $iCharHeight * 2 ; 32 on my PC (16 * 2)
Global $i_Gui_Width
Global $i_Gui_Height
Global $nH_Pos, $nV_Pos, $iIncMini = 0

; _Create_Schrollbars() ; Create Schrollbars
Global $iScroll_Width = _WinAPI_GetSystemMetrics(2) ; Width of VScrollbar:  SM_CXVSCROLL
Global $iScroll_Height = _WinAPI_GetSystemMetrics(3) ; Height of HScrollbar: SM_CYHSCROLL
; ConsoleWrite($iScroll_Width & "   " & $iScroll_Height & @crlf) ; 17 & 17 on my PC

; _Create_Keys() ; Create Keys
Global $s_Key_Name

MsgBox(262208, _ ; $MB_TOPMOST + $MB_ICONINFORMATION
        "Resizing Gui with both Scrollbars Example", _
            "Use the 'Pause' key to increment Gui rows & cols" & @CRLF & @CRLF & _
            "and the 'Escape' key to exit script." & @CRLF & @CRLF & _
            "Scroll to end of Gui to see row & cols of keys" & @CRLF & _
            "which shows consistent spacing.")

GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")
GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")

_Increment() ; Increment

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch

    If BitAND(WinGetState($h_GUI), $WIN_STATE_MINIMIZED) Then ; Minimize button, Win-D, hide all
        $iIncMini += 1
        If $iIncMini = 1 Then
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_BOTH, False)
            $nH_Pos = _GUIScrollBars_GetScrollPos($h_GUI, $SB_HORZ)
            $nV_Pos = _GUIScrollBars_GetScrollPos($h_GUI, $SB_VERT)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_HORZ, 0)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_VERT, 0)
        EndIf
    Else ; not Minimized
        If $iIncMini Then
            $iIncMini = 0
            _GUIScrollBars_ShowScrollBar($h_GUI, $SB_BOTH, True)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_HORZ, $nH_Pos)
            _GUIScrollBars_SetScrollInfoPos($h_GUI, $SB_VERT, $nV_Pos)
        EndIf
    EndIf
WEnd

;==============================================
Func _Increment() ; Increment
    GUIDelete($h_Gui)

    ; As the script deletes the GUI for each increment, no need to keep useless rows...
    ; ... in the GLOBAL array $__g_aSB_WindowInfo[][] declared in GuiScrollBars.au3
    ; But it's also a good idea to keep the "useless" rows to check the changed values.
    ; Global $__g_aSB_WindowInfo[1][8] ; reset, exactly as found in GuiScrollBars.au3
    ; _ArrayDisplay($__g_aSB_WindowInfo, "$__g_aSB_WindowInfo", Default, $ARRAYDISPLAY_NOROW)

    $i_Rows += $i_Increment
    $i_Gui_Height = $i_Key_Height * $i_Rows

    $i_Cols += $i_Increment
    $i_Gui_Width = $i_Key_Width * $i_Cols

    _Create_Gui() ; Create Gui
    _Create_Schrollbars() ; Create Schrollbars
    _Create_Keys() ; Create Keys
    GUISetState(@SW_SHOW, $h_Gui)

EndFunc ; ==> _Increment

;========================================================
Func _Create_Gui() ; Create Gui
    $h_Gui = GUICreate("Resizing Gui", _
                        $i_Gui_Width / 2 + $iScroll_Width, _
                        $i_Gui_Height / 2 + $iScroll_Height, _
                        Default, _
                        Default, _
                        Default, _
                        $WS_EX_TOPMOST)
EndFunc ; ==> _Create_Gui

;========================================================
Func _Create_Schrollbars() ; Create Schrollbars

    Local $aRet = _GUIScrollbars_Size($i_Gui_Width - $iScroll_Width / 2, $i_Gui_Height - $iScroll_Height / 2, _
        $i_Gui_Width / 2 + $iScroll_Width, $i_Gui_Height / 2 + $iScroll_Height)
    ; ConsoleWrite("$aRet[0] = " & $aRet[0] & "   $aRet[1] = " & $aRet[1] & _
    ;   "   $aRet[2] = " & $aRet[2] & "   $aRet[3] = " & $aRet[3] & @crlf)

    ; _GUIScrollBars_Init($h_GUI) ; phantom scrollbar + gap when no 2nd / 3rd param.
    _GUIScrollBars_Init($h_GUI, 1500, 100) ; 2nd & 3rd parameter to increase the values

    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_HORZ, True)
    _GUIScrollBars_SetScrollInfoPage($h_GUI, $SB_HORZ, $aRet[0])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_HORZ, $aRet[1] + 1) ; (+ 1 after test)

    _GUIScrollBars_ShowScrollBar($h_GUI, $SB_VERT, True)
    _GUIScrollBars_SetScrollInfoPage($h_GUI, $SB_VERT, $aRet[2])
    _GUIScrollBars_SetScrollInfoMax($h_GUI, $SB_VERT, $aRet[3])
EndFunc ; ==> _Create_Schrollbars

;========================================================
Func _Create_Keys() ; Create Keys
    For $row = 0 To $i_Rows - 1
        For $col = 0 To $i_Cols - 1
            $s_Key_Name = $row + 1 & "." & $col + 1

            GUICtrlCreateLabel($s_Key_Name, _
                                ($col) * $i_Key_Width, _
                                ($row) * $i_Key_Height, _
                                $i_Key_Width, _
                                $i_Key_Height, _
                                BitOr($SS_CENTERIMAGE, $SS_CENTER, $SS_SUNKEN), _
                                $GUI_WS_EX_PARENTDRAG)

            GUICtrlSetTip(-1, _
                            $i_Key_Width & "w x " & _
                            $i_Key_Height & "h x " & _
                            $i_Rows & " rows")
             GUICtrlSetBkColor(-1, _
                                 0xFFFFFF) ; White
            GUICtrlSetFont(-1, _
                            Default, _
                            900) ; Bold
        Next
    Next
EndFunc ; ==> _Create_Keys

;========================================================
Func _Exit() ; Exit
    Exit
EndFunc ; ==> _Exit

;========================================================
Func _Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)

    #forceref $Msg, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
    Local $iIndex = -1, $xChar, $xPos
    Local $Page, $Pos, $TrackPos

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

    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    $xPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $xPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    Switch $nScrollCode
        Case $SB_LINELEFT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
        Case $SB_LINERIGHT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
        Case $SB_PAGELEFT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
        Case $SB_PAGERIGHT
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
        Case $SB_THUMBTRACK
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

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

    $Pos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($Pos <> $xPos) Then _GUIScrollBars_ScrollWindow($hWnd, $xChar * ($xPos - $Pos), 0)

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_HSCROLL

;========================================================
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

1174962787_Scrollbarsgoodrestore2.png.1cf289f2aad0dcdfaf8f62257ca0b51b.png

So this is the end of our "scrollbar journey". Thank you for this interesting challenge and to Melba23 for his continuous help.
Have a great sunday :)

Edited by pixelsearch
While... Wend loop more robust, taking care of Minimize button, Win-D, hide all
Link to comment
Share on other sites

Glad you liked the scripts, taurus905

In a few minutes, I'm gonna amend the While...Wend loop of 2 other scripts above (the vertical one and the horizontal one) to get a more robust loop, so all 3 scripts will behave correctly when the gui is restored after it was minimized using Win-D or "hide all" button from taskbar, as Melba23 indicated  in this link

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...