Jump to content

Scrollbars Made Easy - New version 27 Jan 22


Melba23
 Share

Recommended Posts

  • Moderators

Malkey and MrCreatoR,

It actually works! :(

How did I miss that when I was searching? :)

Thanks a lot to both of you - I will work on a modified version later today! :)

M23

Edit: Just seen MrCreatorR's earlier posts and did not want him to feel left out. :idea:

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

  • Moderators

Hi,

Here is a stand-alone script using a new version of the _GUIScrollbars_Generate function which incorporates mouse scroll wheel support - horizontal scrolling is either by the horizontal wheel or by pressing Ctrl or Shft and using the vertical wheel:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiScrollBars.au3>
#include <ScrollBarConstants.au3>
#include <SendMessage.au3>

Global $aSB_WindowInfo[1][8]

$hGUI = GUICreate("Test", 400, 300)

For $i = 1 To 20
    For $j = 1 To 20
        GUICtrlCreateLabel(($i - 1) * 20 + $j, 10 + 85 * ($i - 1), 10 + 30 * ($j - 1), 75, 25)
    Next
Next

; Generate scrollbars
_GUIScrollbars_Generate($hGUI, 85 * 19 + 75, 30 * 19 + 25)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func _GUIScrollbars_Generate($hWnd, $iH_Scroll = 0, $iV_Scroll = 0, $iH_Tight = 0, $iV_Tight = 0, $fBefore = False)

    ; Check if valid window handle
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If $aSB_WindowInfo[0][0] <> "" Then ReDim $aSB_WindowInfo[UBound($aSB_WindowInfo) + 1][8]

    ; If no scroll sizes set, return error
    If $iH_Scroll = 0 And $iV_Scroll = 0 Then Return SetError(2, 0, 0)

    ; Confirm Tight values
    If $iH_Tight <> 0 Then $iH_Tight = 1
    If $iV_Tight <> 0 Then $iV_Tight = 1

    ; Create structs
    Local $tTEXTMETRIC = DllStructCreate($tagTEXTMETRIC)
    Local $tSCROLLINFO = DllStructCreate($tagSCROLLINFO)
    DllStructSetData($tSCROLLINFO, "cbSize", DllStructGetSize($tSCROLLINFO))
    Local $tRect = DllStructCreate($tagRECT)

    ; Declare local variables
    Local $iIndex = UBound($aSB_WindowInfo) - 1
    Local $iError, $iExtended

    ; Save window handle
    $aSB_WindowInfo[$iIndex][0] = $hWnd

    ; Determine text size
    Local $hDC = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hWnd)
    If Not @error Then
        $hDC = $hDC[0]
        DllCall("gdi32.dll", "bool", "GetTextMetricsW", "handle", $hDC, "ptr", DllStructGetPtr($tTEXTMETRIC))
        If @error Then
            $iError = @error
            $iExtended = @extended
            DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
            Return SetError($iError, $iExtended, -2)
        EndIf
        DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
    Else
        Return SetError(@error, @extended, -1)
    EndIf
    $aSB_WindowInfo[$iIndex][2] = DllStructGetData($tTEXTMETRIC, "tmAveCharWidth")
    $aSB_WindowInfo[$iIndex][3] = DllStructGetData($tTEXTMETRIC, "tmHeight") + DllStructGetData($tTEXTMETRIC, "tmExternalLeading")

    ; Size aperture window without bars
    DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    If @error Then Return SetError(@error, @extended, -3)
    Local $iX_Client_Full = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    Local $iY_Client_Full = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $aSB_WindowInfo[$iIndex][4] = $iX_Client_Full
    $aSB_WindowInfo[$iIndex][5] = $iY_Client_Full

    ; Register scrollbar and mousewheel messages
    GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")
    GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")
    GUIRegisterMsg($WM_MOUSEWHEEL, "_Scrollbars_WM_MOUSEWHEEL")
    GUIRegisterMsg($WM_MOUSEHWHEEL, '_Scrollbars_WM_MOUSEHWHEEL')

    ; Show scrollbars
    _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, False)
    If $iH_Scroll Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ)
    If $iV_Scroll Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT)

    ; Size aperture window with bars
    DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    If @error Then Return SetError(@error, @extended, -3)
    Local $iX_Client_Bar = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    Local $iY_Client_Bar = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")

    ; If horizontal scrollbar is required
    Local $iH_FullPage
    If $iH_Scroll Then
        If $fBefore Then
            ; Use actual aperture width
            $aSB_WindowInfo[$iIndex][4] = $iX_Client_Bar
            ; Determine page size (aperture width / text width)
            $iH_FullPage = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
            ; Determine max size (scroll width / text width - tight)
            $aSB_WindowInfo[$iIndex][6] = Floor($iH_Scroll / $aSB_WindowInfo[$iIndex][2]) - $iH_Tight
        Else
            ; Use reduced aperture width only if other scrollbar exists
            If $iV_Scroll Then $aSB_WindowInfo[$iIndex][4] = $iX_Client_Bar
            ; Determine page size (aperture width / text width)
            $iH_FullPage = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
            ; Determine max size (scroll width / text width * correction factor for V scrollbar if required - tight)
            $aSB_WindowInfo[$iIndex][6] = Floor($iH_Scroll / $aSB_WindowInfo[$iIndex][2] * $aSB_WindowInfo[$iIndex][4] / $iX_Client_Full) - $iH_Tight
        EndIf
    Else
        $aSB_WindowInfo[$iIndex][6] = 0
    EndIf

    ; If vertical scrollbar required
    Local $iV_FullPage
    If $iV_Scroll Then
        If $fBefore Then
            ; Use actual aperture height
            $aSB_WindowInfo[$iIndex][5] = $iY_Client_Bar
            ; Determine page size (aperture width / text width)
            $iV_FullPage = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])
            ; Determine max size (scroll width / text width - tight)
            $aSB_WindowInfo[$iIndex][7] = Floor($iV_Scroll / $aSB_WindowInfo[$iIndex][3]) - $iV_Tight
        Else
            ; Use reduced aperture width only if other scrollbar exists
            If $iH_Scroll Then $aSB_WindowInfo[$iIndex][5] = $iY_Client_Bar
            ; Determine page size (aperture width / text width)
            $iV_FullPage = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])
            ; Determine max size (scroll width / text width * correction factor for H scrollbar if required - tight)
            $aSB_WindowInfo[$iIndex][7] = Floor($iV_Scroll / $aSB_WindowInfo[$iIndex][3] * $aSB_WindowInfo[$iIndex][5] / $iY_Client_Full) - $iV_Tight
        EndIf
    Else
        $aSB_WindowInfo[$iIndex][7] = 0
    EndIf

    Local $aRet[4]
    If $iV_Scroll Then
        $aRet[0] = $iX_Client_Bar
    Else
        $aRet[0] = $iX_Client_Full
    EndIf
    If $iH_Scroll Then
        $aRet[1] = $iY_Client_Bar
    Else
        $aRet[1] = $iY_Client_Full
    EndIf
    $aRet[2] = $iX_Client_Bar / $iX_Client_Full
    $aRet[3] = $iY_Client_Bar / $iY_Client_Full

    Local $fSuccess = True
    If _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, False) = False Then $fSuccess = False
    If $iH_Scroll Then
        If _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_HORZ, $aSB_WindowInfo[$iIndex][6]) = False Then $fSuccess = False
        _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_HORZ, $iH_FullPage)
        If @error Then $fSuccess = False
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, True) = False Then $fSuccess = False
    Else
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False) = False Then $fSuccess = False
    EndIf
    If $iV_Scroll Then
        If _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_VERT, $aSB_WindowInfo[$iIndex][7]) = False Then $fSuccess = False
        _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_VERT, $iV_FullPage)
        If @error Then $fSuccess = False
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, True) = False Then $fSuccess = False
    Else
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, False) = False Then $fSuccess = False
    EndIf

    If $fSuccess Then Return $aRet
    Return SetError(3, 0, 0)

EndFunc   ;==>_GUIScrollbars_Generate

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($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $yChar = $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

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($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $xChar = $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_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    Local $iDirn, $iDelta = BitShift($wParam, 16)

    If BitAND($wParam, 0x0000FFFF) Then ; If Ctrl or Shft pressed move Horz scrollbar
        $iDirn = $SB_LINERIGHT
        If $iDelta > 0 Then $iDirn = $SB_LINELEFT
        For $i = 1 To 10
            _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
        Next
    Else ; Move Vert scrollbar
        $iDirn = $SB_LINEDOWN
        If $iDelta > 0 Then $iDirn = $SB_LINEUP
        _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEWHEEL

Func _Scrollbars_WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)

    Local $iDirn, $iDelta = BitShift($wParam, 16)

    Local $iDirn = $SB_LINERIGHT
    If $iDelta > 0 Then $iDirn = $SB_LINELEFT
    For $i = 1 To 10
        _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
    Next

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEHWHEEL

It works well on my machine using the vertical wheel, but I do not have a horizontal wheel on my mouse to test. So before I release the new version of the UDF to the wider community, could some kind soul please test this stand-alone version and confirm that it does work with a horizontal wheel (and in the correct sense! :) )

Thanks in advance, :idea:

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

  • Moderators

Mouse wheel scrolling now incorporated. Mythanks to MrCreatoR and Malkey for the pointers. :idea:

See first post for new script and zip.

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

Mouse wheel scrolling now incorporated. Mythanks to MrCreatoR and Malkey for the pointers. :idea:

See first post for new script and zip.

M23

Awesome changes Melba23, Great work Posted Image

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

I'll be getting this first thing in the morning- I'm in the middle of a big script with the potential for up to 6 scrolling child GUIs and was bemoaning my inability to have any confidence that my math would always work out in controlling how far each one scrolled...so a BIG, HUGE THANKS to Melba and everyone who contributed.

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

  • 4 weeks later...

Hi Melba23,

I am not understanding 1 thing in your UDF,

Please see the images :

Test 1:

post-36752-12752649952699_thumb.jpg

Test 2:

post-36752-12752650350226_thumb.jpg

As you can see in Test 2 when i change the scroll position, New Label is not accurate as in Test 1.

What is the reason of it & how can i control this situation?

Regards;

Digisoul

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

  • 2 weeks later...
  • Moderators

Digisoul,

Sorry for the delay in replying, I was away for a few days.

That was an interesting question - now I know a little bit more about how scrollbars work! :party: It is not my UDF that causes the problem - I am delighted to say - it is Windows itself.

It seems that any new controls are created relative the the visual area of the scrolled GUI, not the actual underlying scrollable area. As I had only ever tried to create controls when the scrollbars were at their intial positions, I hade not realised this. To get the control to appear at the correct place if the scrollbars have been moved, we have to correct for the distance the scrollbars have moved the underlying area. The actual calculations are very simple, but it annoying to have to make them - I would have hoped that Windows was intelligent enough to do it for you. Obviously not! :P

The value of the correction is calculated by getting the value of the scrollbar thumb position and then multiplying by the number of pixels in each "click" of the scrollbar. We can find that by dividing the required scrollable size by the Maximum value set for the scrollbar and converting it to an integer:

Scrollbar Position * Int(Scrollable Size / Scrollbar Max Position)

Here is a version of the example with an additional function to calculate the corrections needed if the scrollbars are moved - look for the <<<<<<<<<<<<<<<<<<<< lines:

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

#include "GUIScrollbars_Size.au3"

Global $hButton_Show_UnCorr = 9999, $hButton_Show_Corr = 9999, $hButton_Show_Size = 9999, $hButton_Show_Dock = 9999

; Set aperture and scroll sizes
$iH_Aperture = 400
$iV_Aperture = 400
$iH_Scroll = 1000
$iV_Scroll = 1000

; Create GUI
$hGUI = GUICreate("Scrollbar Test", $iH_Aperture, $iV_Aperture)
GUISetBkColor(0xD0D0FF, $hGUI)

; Create buttons
$hButton_Size = GUICtrlCreateButton("Pass Size",  10, 10, 80, 30)
$sMsg = "Pressing 'Pass Size' runs the function BEFORE the scrollbars are" & @CRLF & _
        "added.  The required size of the aperture is passed." & @CRLF & @CRLF &  _
        "Controls should be created AFTER the scrollbars are created."
$hLabel_Size = GUICtrlCreateLabel($sMsg, 10, 50, $iH_Aperture - 20, 50)
$hButton_Handle = GUICtrlCreateButton("Pass Handle", 10, 150, 80, 30)
$sMsg = "Pressing 'Pass Handle' runs the function AFTER the scrollbars are" & @CRLF & _
        "added.  The GUI handle is passed." & @CRLF & @CRLF &  _
        "Controls should be created BEFORE the scrollbars are created"
$hLabel_Handle = GUICtrlCreateLabel($sMsg, 10, 200, $iH_Aperture - 20, 50)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $hButton_Size
            GUICtrlSetState($hButton_Size, $GUI_HIDE)
            GUICtrlSetState($hButton_Handle, $GUI_HIDE)
            GUICtrlDelete($hLabel_Size)
            GUICtrlDelete($hLabel_Handle)
            ; Get scrollbar values BEFORE showing bars
            $aRet = _GUIScrollbars_Size($iH_Scroll, $iV_Scroll, $iH_Aperture, $iV_Aperture)
            If @error Then
                MsgBox(0, "Error", "Sizing error" & @CRLF & _
                        "Return: " & $aRet & @CRLF & _
                        "Error: " & @error & @CRLF & _
                        "Extended: " & @extended)
                Exit
            Else
                For $i = 0 To 5
                    ConsoleWrite($aRet[$i]  & @CRLF)
                Next
            EndIf
            ; Register scrollbar messages
            GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")
            GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")
            ; Show scrollbars
            _GUIScrollBars_Init($hGUI)
            ; Set scrollbar limits
            _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_HORZ, $aRet[0])
            _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_HORZ, $aRet[1])
            _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
            _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])

            $sMsg = "The buttons and labels below have been created AFTER" & @CRLF & _
                    "the scrollbars.  Pressing the buttons will show that there" & @CRLF & _
                    "is no requirement to apply the correction factors to either" & @CRLF & _
                    "normal or DOCKALL controls"
            GUICtrlCreateLabel($sMsg, 10, 10, $iH_Aperture - 20, 90)

            $hButton_Show_UnCorr = GUICtrlCreateButton("Show UnCorr", 100, 150, 85, 30)
            $hButton_Show_Dock = GUICtrlCreateButton("Show DOCKALL", 100, 300, 85, 30)

            ; Show preset positions
            GUICtrlCreateLabel("", 200, 150, 90, 30)
            GUICtrlSetBkColor(-1, 0)
            GUICtrlCreateLabel("200x150", 200, 150, 80, 30)
            GUICtrlSetBkColor(-1, 0xC4C4C4)
            GUICtrlCreateLabel("", 200, 300, 90, 30)
            GUICtrlSetBkColor(-1, 0)
            GUICtrlCreateLabel("200x300" & @CRLF & "DOCKALL", 200, 300, 80, 30)
            GUICtrlSetBkColor(-1, 0xC4C4C4)
            GUICtrlSetResizing(-1, $GUI_DOCKALL)

            ;; Show edges
            If $iH_Scroll = 0 Then
                GUICtrlCreateLabel("", 0, $iV_Scroll, $iH_Aperture, 3)
                GUICtrlSetBkColor(-1, 0xFF0000)
            ElseIf $iV_Scroll = 0 Then
                GUICtrlCreateLabel("", $iH_Scroll, 0, 3, $iV_Aperture)
                GUICtrlSetBkColor(-1, 0xFF0000)
            Else
                GUICtrlCreateLabel("", $iH_Scroll, 0, 3, $iV_Scroll)
                GUICtrlSetBkColor(-1, 0xFF0000)
                GUICtrlCreateLabel("", 0, $iV_Scroll, $iH_Scroll + 3, 3)
                GUICtrlSetBkColor(-1, 0xFF0000)
            EndIf

            $sMsg = "As the GUI has not been resized," & @CRLF & _
                "the corner position remains:" & @CRLF & _
                $iH_Scroll & " x " & $iV_Scroll
            GUICtrlCreateLabel($sMsg, $iH_Scroll - 210, $iV_Scroll - 50, 200, 50, 2)

        Case $hButton_Handle
            GUICtrlSetState($hButton_Size, $GUI_HIDE)
            GUICtrlSetState($hButton_Handle, $GUI_HIDE)
            GUICtrlDelete($hLabel_Size)
            GUICtrlDelete($hLabel_Handle)
            $sMsg = "The buttons and labels below have been created BEFORE" & @CRLF & _
                    "the scrollbars.  They will be slightly moved and resized as" & @CRLF & _
                    "the GUI shrinks to the new client area size.  Pressing the" & @CRLF & _
                    "buttons will show the result of applying (or not) the" & @CRLF & _
                    "correction factors." & @CRLF & _
                    "Note the DOCKALL label remains in position"
            GUICtrlCreateLabel($sMsg, 10, 10, $iH_Aperture - 20, 90)

            $hButton_Show_UnCorr = GUICtrlCreateButton("Show UnCorr", 100, 150, 85, 30)
            $hButton_Show_Corr = GUICtrlCreateButton("Show Corr Pos", 100, 200, 85, 30)
            $hButton_Show_Size = GUICtrlCreateButton("Show Corr Size", 100, 250, 85, 30)
            $hButton_Show_Dock = GUICtrlCreateButton("Show DOCKALL", 100, 300, 85, 30)

            ; Show preset positions
            GUICtrlCreateLabel("", 200, 150, 90, 30)
            GUICtrlSetBkColor(-1, 0)
            GUICtrlCreateLabel("200x150", 200, 150, 80, 30)
            GUICtrlSetBkColor(-1, 0xC4C4C4)
            GUICtrlCreateLabel("", 200, 200, 90, 30)
            GUICtrlSetBkColor(-1, 0)
            GUICtrlCreateLabel("200x200", 200, 200, 80, 30)
            GUICtrlSetBkColor(-1, 0xC4C4C4)
            GUICtrlCreateLabel("", 200, 250, 90, 30)
            GUICtrlSetBkColor(-1, 0)
            GUICtrlCreateLabel("200x250", 200, 250, 80, 30)
            GUICtrlSetBkColor(-1, 0xC4C4C4)
            GUICtrlCreateLabel("", 200, 300, 90, 30)
            GUICtrlSetBkColor(-1, 0)
            GUICtrlSetResizing(-1, $GUI_DOCKALL)
            GUICtrlCreateLabel("200x300" & @CRLF & "DOCKALL", 200, 300, 80, 30)
            GUICtrlSetBkColor(-1, 0xC4C4C4)
            GUICtrlSetResizing(-1, $GUI_DOCKALL)

            ; Show edges
            If $iH_Scroll = 0 Then
                GUICtrlCreateLabel("", 0, $iV_Scroll, $iH_Aperture, 3)
                GUICtrlSetBkColor(-1, 0xFF0000)
            ElseIf $iV_Scroll = 0 Then
                GUICtrlCreateLabel("", $iH_Scroll, 0, 3, $iV_Aperture)
                GUICtrlSetBkColor(-1, 0xFF0000)
            Else
                GUICtrlCreateLabel("", $iH_Scroll, 0, 3, $iV_Scroll)
                GUICtrlSetBkColor(-1, 0xFF0000)
                GUICtrlCreateLabel("", 0, $iV_Scroll, $iH_Scroll + 3, 3)
                GUICtrlSetBkColor(-1, 0xFF0000)
            EndIf

            $hButton_Create = GUICtrlCreateButton("Create Scrollbars", 10, 110, 160, 30)

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

            ; Register scrollbar messages
            GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")
            GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")
            ; Show scrollbars
            _GUIScrollBars_Init($hGUI)
            _GUIScrollBars_ShowScrollBar($hGUI, $SB_BOTH, True)
            If $iH_Scroll = 0 Then _GUIScrollBars_ShowScrollBar($hGUI, $SB_HORZ, False)
            If $iV_Scroll = 0 Then _GUIScrollBars_ShowScrollBar($hGUI, $SB_VERT, False)

            ; Get scrollbar values AFTER showing bars
            $aRet = _GUIScrollbars_Size($iH_Scroll, $iV_Scroll, $hGUI)
            If @error Then
                MsgBox(0, "Error", "Sizing error" & @CRLF & _
                        "Return: " & $aRet & @CRLF & _
                        "Error: " & @error & @CRLF & _
                        "Extended: " & @extended)
                Exit
            Else
                For $i = 0 To 5
                    ConsoleWrite($aRet[$i]  & @CRLF)
                Next
            EndIf
            ; Set scrollbar limits
            _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_HORZ, $aRet[0])
            _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_HORZ, $aRet[1])
            _GUIScrollBars_SetScrollInfoPage($hGUI, $SB_VERT, $aRet[2])
            _GUIScrollBars_SetScrollInfoMax($hGUI, $SB_VERT, $aRet[3])

            $sMsg = "As the GUI has been resized," & @CRLF & _
                "the corner position is now:" & @CRLF & _
                Int($iH_Scroll * $aRet[4]) & " x " & Int($iV_Scroll * $aRet[5])
            GUICtrlCreateLabel($sMsg, ($iH_Scroll * $aRet[4]) - 210, ($iV_Scroll * $aRet[5]) - 50, 200, 50, 2)

        Case $hButton_Show_UnCorr
            ; Add label with uncorrected coordinates
            $aCorr = _Scroll_Move_Corr($hGUI) ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Get correction factors
            GUICtrlCreateLabel("200x150" & @CRLF & "UnCorrected", 200 - $aCorr[0], 150 - $aCorr[1], 80, 30)
            GUICtrlSetBkColor(-1, 0xFFC4C4)
            GUICtrlSetState($hButton_Show_UnCorr, $GUI_DISABLE)
        Case $hButton_Show_Corr
            ; Add label with corrected coordinates
            $aCorr = _Scroll_Move_Corr($hGUI)
            GUICtrlCreateLabel("200x200" & @CRLF & "Corr Position", 200 * $aRet[4] - $aCorr[0], 200 * $aRet[5] - $aCorr[1], 80, 30)
            GUICtrlSetBkColor(-1, 0xFFD000)
            GUICtrlSetState($hButton_Show_Corr, $GUI_DISABLE)
        Case $hButton_Show_Size
            ; Add label with corrected coordinates
            $aCorr = _Scroll_Move_Corr($hGUI)
            GUICtrlCreateLabel("200x250" & @CRLF & "Corr Pos + Size", 200 * $aRet[4] - $aCorr[0], 250 * $aRet[5] - $aCorr[1], 80 * $aRet[4], 30 * $aRet[5])
            GUICtrlSetBkColor(-1, 0xC4FFC4)
            GUICtrlSetState($hButton_Show_Size, $GUI_DISABLE)
        Case $hButton_Show_Dock
            ; Add label with uncorrected coordinates
            $aCorr = _Scroll_Move_Corr($hGUI)
            GUICtrlCreateLabel("200x300" & @CRLF & "DOCKALL", 200 - $aCorr[0], 300 - $aCorr[1], 80, 30)
            GUICtrlSetBkColor(-1, 0xC4FFC4)
            GUICtrlSetState($hButton_Show_Dock, $GUI_DISABLE)
    EndSwitch

WEnd

Func _Scroll_Move_Corr($hWnd) ; <<<<<<<<<<<<<<<<<<<<<< Calculate correction factors

    Local $aCorr[2]
    $aCorr[0] = _GUIScrollBars_GetScrollInfoPos($hWnd, $SB_HORZ) * Int($iH_Scroll / _GUIScrollBars_GetScrollInfoMax($hWnd, $SB_HORZ))
    $aCorr[1] = _GUIScrollBars_GetScrollInfoPos($hWnd, $SB_VERT) * Int($iV_Scroll / _GUIScrollBars_GetScrollInfoMax($hWnd, $SB_VERT))

    Return $aCorr

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($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $yChar = $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

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($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $xChar = $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 hope that answers both your questions! :mellow:

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

  • Moderators

Following DigiSoul's discovery that controls are still located relative to the framing GUI rather than the underlying scrollable area, and maintaining my ambition to make the scrollbar process as painless as possible, I have added a function to the GUIScrollBars_Ex UDF.

This function, _GUIScrollbars_Locate_Ctrl, will do all the calculations necessary to position any new controls where you would expect them to be rather than where Windows thinks they should be. All you need to pass as parameters are the handle of the window containing the scrollbars and the required coordinates of the control on the underlying scrollable area. The function returns a 2 element array holding the corrected coordinates - use these and your control will be located where you want it to be. :mellow:

Here is a short example script. The 2 GUIs differ in having the scrollbars created BEFORE and AFTER the coloured label. In the original version, the user had to remember to factor the coordinates in the BEFORE case but now the UDF does that automatically. Try moving the scrollbars so that the label changes position - the UDF will compensate for this. Basically, the new label will always overlay the original:

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

; Create GUI 1
$hGUI_1 = GUICreate("BEFORE", 500, 400, 100, 100)

$hButton_1 = GUICtrlCreateButton("Press", 400, 300, 80, 30)

GUISetState()

; Generate scrollbars BEFORE controls
_GUIScrollbars_Generate($hGUI_1, 1000, 1000, 0, 0, True)

$hLabel_1 = GUICtrlCreateLabel("", 300, 200, 50, 50)
GUICtrlSetBkColor(-1, 0xCCCCFF)

; Create GUI 2
$hGUI_2 = GUICreate("AFTER", 500, 400, 700, 100)

$hLabel_2 = GUICtrlCreateLabel("", 200, 300, 50, 50)
GUICtrlSetBkColor(-1, 0xCCCCFF)

$hButton_2 = GUICtrlCreateButton("Press", 400, 300, 80, 30)

GUISetState()

; Generate scrollbars AFTER controls
_GUIScrollbars_Generate($hGUI_2, 700, 700)

While 1

    $aMsg = GUIGetMsg(1)
    Switch $aMsg[1]
        Case $hGUI_1
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    Exit
                Case $hButton_1
                    GUISwitch($hGUI_1)
                    $aPos = _GUIScrollbars_Locate_Ctrl($hGUI_1, 300, 200)
                    $hNewLabel_1 = GUICtrlCreateLabel("",$aPos[0], $aPos[1], 50, 50)
                    GUICtrlSetBkColor(-1, 0xCCFFCC)
                    Sleep(1000)
                    GUICtrlDelete($hNewLabel_1)
            EndSwitch
        Case $hGUI_2
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    Exit
                Case $hButton_2
                    GUISwitch($hGUI_2)
                    $aPos = _GUIScrollbars_Locate_Ctrl($hGUI_2, 200, 300)
                    $hNewLabel_2 = GUICtrlCreateLabel("",$aPos[0], $aPos[1], 50, 50)
                    GUICtrlSetBkColor(-1, 0xCCFFCC)
                    Sleep(1000)
                    GUICtrlDelete($hNewLabel_2)
            EndSwitch
    EndSwitch
WEnd

And the new UDF:

#include-once

; #INDEX# ============================================================================================================
; Title .........: GUIScrollBars_Ex
; AutoIt Version : v3.3.6.0
; Language ......: English
; Description ...: Generates scrollbars for user defined sizes of GUI and aperture and sets proportional thumb sizes
; Remarks .......:
; Note ..........:
; Author(s) .....: Melba23 - with some code based on the WinAPI and GUIScrollBars includes, and from MrCreatoR & Malkey
; ====================================================================================================================

;#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

; #INCLUDES# =========================================================================================================
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiScrollBars.au3>
#include <ScrollBarConstants.au3>
#include <SendMessage.au3>

; #GLOBAL VARIABLES# =================================================================================================
Global $aSB_WindowInfo[1][8]
; [0] = Handle to window
; [1] = Not used
; [2] = Average horizontal pixels per char
; [3] = Vertical pixels per char
; [4] = Client area width
; [5] = Client area height
; [6] = Horizontal max setting
; [7] = Vertical max setting

Global $aSB_WindowInfoEx[1][5]
; [0] = Horizontal scrollable size
; [1] = Vertical scrollable size
; [2] = Width correction factor
; [3] = Height correction factor
; [4] = Before/After flag

; #CURRENT# ==========================================================================================================
; _GUIScrollbars_Generate:    Generates scrollbars for a GUI with a defined aperture with proportional thumb sizes
; _GUIScrollbars_Locate_Ctrl: Calculates coordinates to use to position controls after scrollbar creation
; _GUIScrollbars_Scroll_Page: Scrolls to min, max or page number
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _Scrollbars_WM_VSCROLL: GUIRegisterMsg procedure for vertical scrollbar
; _Scrollbars_WM_HSCROLL: GUIRegisterMsg procedure for horizontal scrollbar
; _Scrollbars_WM_MOUSEWHEEL : GUIRegisterMsg procedure for vertical mouse wheel scroll
; _Scrollbars_WM_MOUSEHWHEEL : GUIRegisterMsg procedure for horizontal mouse wheel scroll
;=====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _GUIScrollbars_Generate
; Description ...: Generates scrollbars for a GUI with a defined aperture with proportional thumb sizes
; Syntax.........: _GUIScrollbars_Generate ($hWnd, $iH_Scroll = 0, [$iV_Scroll = 0, [$iH_Tight = 0, [$iV_Tight = 0, [$fBefore = False]]]])
; Parameters ....: $hWnd      -> GUI to contain scrollbars
;                  $iH_Scroll -> Width in pixels of area to be scrolled
;                  $iV_Scroll -> Height in pixels of area to be scrolled (default = 0)
;                  $iH_Tight  -> 1 = Adjust mean position of right edge of scrolled area to right (default = 0)
;                  $iV_Tight  -> 1 = Adjust mean position of bottom edge of scrolled area down (default = 0)
;                  $fBefore   -> True  = Scrollbars are being generated BEFORE controls
;                                False = Scrollbars are being generated AFTER controls (default)
; Requirement(s).: v3.3.6.0 or higher
; Return values .: Success - Returns a 4-element array (see remarks for details):
;                            [0] = Actual aperture width ; [1] = Actual aperture height]
;                            [2] = Width correction factor ; [3] = Height correction factor]
;                  Failure - Returns either 0 (UDF error) or negative integer (API error)
;                            If UDF error then @error set as follows:
;                               1 - hWnd not a valid handle
;                               2 - No scroll size parameters
;                               3 - Scrollbar creation or parameter setting failure
;                            If API error then @error and @extended as set by API error.  Return values:
;                               -1 - GetDC failure
;                               -2 - GetTextMetricsW failure
;                               -3 - GetClientRect failure
; Remarks .......; The $fBefore parameter is needed because of the way Windows deals with scrollbars.  When the
;                  scrollbars are generated, the visible part of the scrollable GUI resizes to fit the in the
;                  remaining (smaller) client area.
;                  - If the scrollbars are to be generated BEFORE any controls, the UDF shoudl be called with the
;                  $fBefore parameter set.  The new client size of the aperture window is returned so that
;                  controls can then be created using these values.
;                  - If controls have been created before the scrollbars are generated then the UDF should be
;                  called without the $fBefore parameter.  The correction factors returned can then be applied to
;                  any subsequent control positioning and sizing.  This is necessary because of the positions and
;                  sizes of existing controls will be slightly altered as the scrollbars are generated and the GUI
;                  resized.  Any controls created subsequently would therefore be slightly misplaced in relation
;                  to the existing ones unless the correction factors are used when positoning and sizing them.
;                  - If existing controls were fixed in place using GUICtrlResizing($GUI_DOCKALL) there is no need
;                  to apply the correction factors as the controls will not have moved with the GUI resizing.
; Author ........: Melba23 - with some code based on the WinAPI and GUIScrollBars includes
; Example........; Yes
;=====================================================================================================================
Func _GUIScrollbars_Generate($hWnd, $iH_Scroll = 0, $iV_Scroll = 0, $iH_Tight = 0, $iV_Tight = 0, $fBefore = False)

    ; Check if valid window handle
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If $aSB_WindowInfo[0][0] <> "" Then
        ReDim $aSB_WindowInfo[UBound($aSB_WindowInfo) + 1][8]
        ReDim $aSB_WindowInfoEx[UBound($aSB_WindowInfo) + 1][5]
    EndIf

    ; If no scroll sizes set, return error
    If $iH_Scroll = 0 And $iV_Scroll = 0 Then Return SetError(2, 0, 0)

    ; Confirm Tight values
    If $iH_Tight <> 0 Then $iH_Tight = 1
    If $iV_Tight <> 0 Then $iV_Tight = 1

    ; Create structs
    Local $tTEXTMETRIC = DllStructCreate($tagTEXTMETRIC)
    Local $tSCROLLINFO = DllStructCreate($tagSCROLLINFO)
    DllStructSetData($tSCROLLINFO, "cbSize", DllStructGetSize($tSCROLLINFO))
    Local $tRect = DllStructCreate($tagRECT)

    ; Declare local variables
    Local $iIndex = UBound($aSB_WindowInfo) - 1
    Local $iError, $iExtended

    ; Save window handle
    $aSB_WindowInfo[$iIndex][0] = $hWnd

    ; Determine text size
    Local $hDC = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hWnd)
    If Not @error Then
        $hDC = $hDC[0]
        DllCall("gdi32.dll", "bool", "GetTextMetricsW", "handle", $hDC, "ptr", DllStructGetPtr($tTEXTMETRIC))
        If @error Then
            $iError = @error
            $iExtended = @extended
            DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
            Return SetError($iError, $iExtended, -2)
        EndIf
        DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
    Else
        Return SetError(@error, @extended, -1)
    EndIf
    $aSB_WindowInfo[$iIndex][2] = DllStructGetData($tTEXTMETRIC, "tmAveCharWidth")
    $aSB_WindowInfo[$iIndex][3] = DllStructGetData($tTEXTMETRIC, "tmHeight") + DllStructGetData($tTEXTMETRIC, "tmExternalLeading")

    ; Size aperture window without bars
    DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    If @error Then Return SetError(@error, @extended, -3)
    Local $iX_Client_Full = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    Local $iY_Client_Full = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $aSB_WindowInfo[$iIndex][4] = $iX_Client_Full
    $aSB_WindowInfo[$iIndex][5] = $iY_Client_Full

    ; Register scrollbar and mousewheel messages
    GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")
    GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")
    GUIRegisterMsg($WM_MOUSEWHEEL, "_Scrollbars_WM_MOUSEWHEEL")
    GUIRegisterMsg($WM_MOUSEHWHEEL, '_Scrollbars_WM_MOUSEHWHEEL')

    ; Show scrollbars
    _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, False)
    If $iH_Scroll Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ)
    If $iV_Scroll Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT)

    ; Size aperture window with bars
    DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    If @error Then Return SetError(@error, @extended, -3)
    Local $iX_Client_Bar = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    Local $iY_Client_Bar = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")

    ; If horizontal scrollbar is required
    Local $iH_FullPage
    If $iH_Scroll Then
        If $fBefore Then
            ; Use actual aperture width
            $aSB_WindowInfo[$iIndex][4] = $iX_Client_Bar
            ; Determine page size (aperture width / text width)
            $iH_FullPage = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
            ; Determine max size (scroll width / text width - tight)
            $aSB_WindowInfo[$iIndex][6] = Floor($iH_Scroll / $aSB_WindowInfo[$iIndex][2]) - $iH_Tight
        Else
            ; Use reduced aperture width only if other scrollbar exists
            If $iV_Scroll Then $aSB_WindowInfo[$iIndex][4] = $iX_Client_Bar
            ; Determine page size (aperture width / text width)
            $iH_FullPage = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
            ; Determine max size (scroll width / text width * correction factor for V scrollbar if required - tight)
            $aSB_WindowInfo[$iIndex][6] = Floor($iH_Scroll / $aSB_WindowInfo[$iIndex][2] * $aSB_WindowInfo[$iIndex][4] / $iX_Client_Full) - $iH_Tight
        EndIf
    Else
        $aSB_WindowInfo[$iIndex][6] = 0
    EndIf

    ; If vertical scrollbar required
    Local $iV_FullPage
    If $iV_Scroll Then
        If $fBefore Then
            ; Use actual aperture height
            $aSB_WindowInfo[$iIndex][5] = $iY_Client_Bar
            ; Determine page size (aperture width / text width)
            $iV_FullPage = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])
            ; Determine max size (scroll width / text width - tight)
            $aSB_WindowInfo[$iIndex][7] = Floor($iV_Scroll / $aSB_WindowInfo[$iIndex][3]) - $iV_Tight
        Else
            ; Use reduced aperture width only if other scrollbar exists
            If $iH_Scroll Then $aSB_WindowInfo[$iIndex][5] = $iY_Client_Bar
            ; Determine page size (aperture width / text width)
            $iV_FullPage = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])
            ; Determine max size (scroll width / text width * correction factor for H scrollbar if required - tight)
            $aSB_WindowInfo[$iIndex][7] = Floor($iV_Scroll / $aSB_WindowInfo[$iIndex][3] * $aSB_WindowInfo[$iIndex][5] / $iY_Client_Full) - $iV_Tight
        EndIf
    Else
        $aSB_WindowInfo[$iIndex][7] = 0
    EndIf

    Local $aRet[4]
    If $iV_Scroll Then
        $aRet[0] = $iX_Client_Bar
    Else
        $aRet[0] = $iX_Client_Full
    EndIf
    If $iH_Scroll Then
        $aRet[1] = $iY_Client_Bar
    Else
        $aRet[1] = $iY_Client_Full
    EndIf
    $aRet[2] = $iX_Client_Bar / $iX_Client_Full
    $aRet[3] = $iY_Client_Bar / $iY_Client_Full

    ; Save extended window info
    $aSB_WindowInfoEx[$iIndex][0] = $iH_Scroll
    $aSB_WindowInfoEx[$iIndex][1] = $iV_Scroll
    $aSB_WindowInfoEx[$iIndex][2] = $aRet[2]
    $aSB_WindowInfoEx[$iIndex][3] = $aRet[3]
    $aSB_WindowInfoEx[$iIndex][4] = $fBefore

    Local $fSuccess = True
    If _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, False) = False Then $fSuccess = False
    If $iH_Scroll Then
        If _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_HORZ, $aSB_WindowInfo[$iIndex][6]) = False Then $fSuccess = False
        _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_HORZ, $iH_FullPage)
        If @error Then $fSuccess = False
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, True) = False Then $fSuccess = False
    Else
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False) = False Then $fSuccess = False
    EndIf
    If $iV_Scroll Then
        If _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_VERT, $aSB_WindowInfo[$iIndex][7]) = False Then $fSuccess = False
        _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_VERT, $iV_FullPage)
        If @error Then $fSuccess = False
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, True) = False Then $fSuccess = False
    Else
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, False) = False Then $fSuccess = False
    EndIf

    If $fSuccess Then Return $aRet
    Return SetError(3, 0, 0)

EndFunc   ;==>_GUIScrollbars_Generate

; #FUNCTION# =========================================================================================================
; Name...........: _GUIScrollbars_Locate_Ctrl
; Description ...: Calculates coordinates to use to position controls after scrollbar creation
; Syntax.........: _GUIScrollbars_Locate_Ctrl ($hWnd, $iX, $iY)
; Parameters ....: $hWnd -> GUI to contain control
;                  $iX   -> Horizontal coordinate relative to scrollable area
;                  $iY   -> Vertical coordinate relative to scrollable area
; Requirement(s).: v3.3.6.0 or higher
; Return values .: Success - Returns a 2-element array:
;                            [0] = Horizontal coordinate
;                            [1] = Vertical coordinate
;                  Failure - Returns either 0 with @error set as follows:
;                            1 - Invalid window handle
;                            2 - Parameter error
;                            3 - Window not found
; Remarks .......;
; Author ........: Melba23
; Example........; Yes
;=====================================================================================================================
Func _GUIScrollbars_Locate_Ctrl($hWnd, $iX, $iY)

    ; Check $hWnd
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)

    ; Find window info
    Local $iIndex = -1
    For $i = 0 To UBound($aSB_WindowInfo) - 1
        If $hWnd = $aSB_WindowInfo[$i][0] Then $iIndex = $i
    Next
    If $iIndex = -1 Then Return SetError(3, 0, 0)

    ; Check if location is within scrollable area of the window
    If $iX < 0 Or $iX > $aSB_WindowInfoEx[$iIndex][0] Then Return SetError(2, 0, 0)
    If $iY < 0 Or $iY > $aSB_WindowInfoEx[$iIndex][1] Then Return SetError(2, 0, 0)

    ; Calculate factored coordinates if needed
    If Not $aSB_WindowInfoEx[$iIndex][4] Then
        $iX *= $aSB_WindowInfoEx[$iIndex][2]
        $iY *= $aSB_WindowInfoEx[$iIndex][3]
    EndIf

    ; Correct for any scrollbar movement
    $iX -= _GUIScrollBars_GetScrollInfoPos($hWnd, $SB_HORZ) * $aSB_WindowInfo[$iIndex][2]
    $iY -= _GUIScrollBars_GetScrollInfoPos($hWnd, $SB_VERT) * $aSB_WindowInfo[$iIndex][3]

    Local $aRet[2] = [$iX, $iY]

    Return $aRet

EndFunc   ;==>_GUIScrollbars_Locate_Ctrl

; #FUNCTION# =========================================================================================================
; Name...........: _GUIScrollbars_Scroll_Page
; Description ...: Scrolls scrollbars generated by _GUIScrollbars_Generate to min, max or page number
; Syntax.........: _GUIScrollbars_Scroll_Page ($hWnd, [$iH_Scroll_Pos = -1, [$iV_Scroll_Pos = -1]])
; Parameters ....: $hWnd          -> GUI to contain scrollbars
;                  $iH_Scroll_Pos -> Horizontal age number:
;                                    0 = No change
;                                    1+ = Scroll to page number
;                                    If page number is over max pages, then scroll to max position
;                  $iV_Scroll_Pos -> As $iH_Scroll_Pos for vertical pages
; Requirement(s).: v3.3.6.0 or higher
; Return values .: None
; Remarks .......;
; Author ........: Melba23
; Example........; Yes
;=====================================================================================================================
Func _GUIScrollbars_Scroll_Page($hWnd, $iH_Scroll_Pos = 0, $iV_Scroll_Pos = 0)

    Local $iPos

    ; Check $hWnd
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)

    ; Check $iH/V_Scroll_Pos
    If Not (IsInt($iH_Scroll_Pos) And IsInt($iV_Scroll_Pos)) Then Return SetError(2, 0, 0)

    ; Find window info
    Local $iIndex = -1
    For $i = 0 To UBound($aSB_WindowInfo) - 1
        If $hWnd = $aSB_WindowInfo[$i][0] Then $iIndex = $i
    Next
    If $iIndex = -1 Then Return SetError(1, 0, 0)

    ; Get page sizes
    Local $iH_Page = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
    Local $iV_Page = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])

    If $iH_Scroll_Pos > 0 Then
        $iPos = ($iH_Scroll_Pos - 1) * $iH_Page
        If $iPos > $aSB_WindowInfo[$iIndex][6] Then $iPos = $aSB_WindowInfo[$iIndex][6]
        _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_HORZ, $iPos)
    EndIf
    If $iV_Scroll_Pos > 0 Then
        $iPos = ($iV_Scroll_Pos - 1) * $iV_Page
        If $iPos > $aSB_WindowInfo[$iIndex][7] Then $iPos = $aSB_WindowInfo[$iIndex][7]
        _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, $iPos)
    EndIf

EndFunc   ;==>_GUIScrollbars_Scroll_Page

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_VSCROLL
; Description ...: GUIRegisterMsg procedure for vertical scrollbar
; Syntax ........: _Scrollbars_WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Taken from AutoIt Help file
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam)

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

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $yChar = $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

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_HSCROLL
; Description ...: GUIRegisterMsg procedure for horizontal scrollbar
; Syntax ........: _Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
; Return values .: None
; Author ........: Taken from AutoIt Help file
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)

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

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $xChar = $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

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_MOUSEWHEEL
; Description ...: GUIRegisterMsg procedure for vertical mouse wheel scroll
; Syntax ........: _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Based on code from MrCreator & Malkey
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn, $iDelta = BitShift($wParam, 16) ; Mouse wheel movement

    If BitAND($wParam, 0x0000FFFF) Then ; If Ctrl or Shft pressed move Horz scrollbar
        $iDirn = $SB_LINERIGHT
        If $iDelta > 0 Then $iDirn = $SB_LINELEFT
        For $i = 1 To 7
            _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
        Next
    Else ; Move Vert scrollbar
        $iDirn = $SB_LINEDOWN
        If $iDelta > 0 Then $iDirn = $SB_LINEUP
        _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEWHEEL

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_MOUSEHWHEEL
; Description ...: GUIRegisterMsg procedure for horizontal mouse wheel scroll
; Syntax ........: _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Based on code from MSDN, MrCreator & Malkey
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = $SB_LINERIGHT
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINELEFT ; Mouse wheel movement
    For $i = 1 To 7
        _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
    Next

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEHWHEEL

Note that the function is only available when the scrollbars have been created using the _GUIScrollbars_Generate function within the UDF as the necessary parameters for the new function are stored within the UDF as the scrollbars are generated. The function has not been added to the _GUIScrollbars_Size UDF for the same reasons. However, I have altered the first _GUIScrollbars_Size example script to show how the user can make the corrections manually (as in the post above).

Zip file in first post updated.

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

Following DigiSoul's discovery that controls are still located relative to the framing GUI rather than the underlying scrollable area, and maintaining my ambition to make the scrollbar process as painless as possible, I have added a function to the GUIScrollBars_Ex UDF.

This function, _GUIScrollbars_Locate_Ctrl, will do all the calculations necessary to position any new controls where you would expect them to be rather than where Windows thinks they should be. All you need to pass as parameters are the handle of the window containing the scrollbars and the required coordinates of the control on the underlying scrollable area. The function returns a 2 element array holding the corrected coordinates - use these and your control will be located where you want it to be. :mellow:

Here is a short example script. The 2 GUIs differ in having the scrollbars created BEFORE and AFTER the coloured label. In the original version, the user had to remember to factor the coordinates in the BEFORE case but now the UDF does that automatically. Try moving the scrollbars so that the label changes position - the UDF will compensate for this. Basically, the new label will always overlay the original:

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

; Create GUI 1
$hGUI_1 = GUICreate("BEFORE", 500, 400, 100, 100)

$hButton_1 = GUICtrlCreateButton("Press", 400, 300, 80, 30)

GUISetState()

; Generate scrollbars BEFORE controls
_GUIScrollbars_Generate($hGUI_1, 1000, 1000, 0, 0, True)

$hLabel_1 = GUICtrlCreateLabel("", 300, 200, 50, 50)
GUICtrlSetBkColor(-1, 0xCCCCFF)

; Create GUI 2
$hGUI_2 = GUICreate("AFTER", 500, 400, 700, 100)

$hLabel_2 = GUICtrlCreateLabel("", 200, 300, 50, 50)
GUICtrlSetBkColor(-1, 0xCCCCFF)

$hButton_2 = GUICtrlCreateButton("Press", 400, 300, 80, 30)

GUISetState()

; Generate scrollbars AFTER controls
_GUIScrollbars_Generate($hGUI_2, 700, 700)

While 1

    $aMsg = GUIGetMsg(1)
    Switch $aMsg[1]
        Case $hGUI_1
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    Exit
                Case $hButton_1
                    GUISwitch($hGUI_1)
                    $aPos = _GUIScrollbars_Locate_Ctrl($hGUI_1, 300, 200)
                    $hNewLabel_1 = GUICtrlCreateLabel("",$aPos[0], $aPos[1], 50, 50)
                    GUICtrlSetBkColor(-1, 0xCCFFCC)
                    Sleep(1000)
                    GUICtrlDelete($hNewLabel_1)
            EndSwitch
        Case $hGUI_2
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    Exit
                Case $hButton_2
                    GUISwitch($hGUI_2)
                    $aPos = _GUIScrollbars_Locate_Ctrl($hGUI_2, 200, 300)
                    $hNewLabel_2 = GUICtrlCreateLabel("",$aPos[0], $aPos[1], 50, 50)
                    GUICtrlSetBkColor(-1, 0xCCFFCC)
                    Sleep(1000)
                    GUICtrlDelete($hNewLabel_2)
            EndSwitch
    EndSwitch
WEnd

And the new UDF:

#include-once

; #INDEX# ============================================================================================================
; Title .........: GUIScrollBars_Ex
; AutoIt Version : v3.3.6.0
; Language ......: English
; Description ...: Generates scrollbars for user defined sizes of GUI and aperture and sets proportional thumb sizes
; Remarks .......:
; Note ..........:
; Author(s) .....: Melba23 - with some code based on the WinAPI and GUIScrollBars includes, and from MrCreatoR & Malkey
; ====================================================================================================================

;#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

; #INCLUDES# =========================================================================================================
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiScrollBars.au3>
#include <ScrollBarConstants.au3>
#include <SendMessage.au3>

; #GLOBAL VARIABLES# =================================================================================================
Global $aSB_WindowInfo[1][8]
; [0] = Handle to window
; [1] = Not used
; [2] = Average horizontal pixels per char
; [3] = Vertical pixels per char
; [4] = Client area width
; [5] = Client area height
; [6] = Horizontal max setting
; [7] = Vertical max setting

Global $aSB_WindowInfoEx[1][5]
; [0] = Horizontal scrollable size
; [1] = Vertical scrollable size
; [2] = Width correction factor
; [3] = Height correction factor
; [4] = Before/After flag

; #CURRENT# ==========================================================================================================
; _GUIScrollbars_Generate:    Generates scrollbars for a GUI with a defined aperture with proportional thumb sizes
; _GUIScrollbars_Locate_Ctrl: Calculates coordinates to use to position controls after scrollbar creation
; _GUIScrollbars_Scroll_Page: Scrolls to min, max or page number
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _Scrollbars_WM_VSCROLL: GUIRegisterMsg procedure for vertical scrollbar
; _Scrollbars_WM_HSCROLL: GUIRegisterMsg procedure for horizontal scrollbar
; _Scrollbars_WM_MOUSEWHEEL : GUIRegisterMsg procedure for vertical mouse wheel scroll
; _Scrollbars_WM_MOUSEHWHEEL : GUIRegisterMsg procedure for horizontal mouse wheel scroll
;=====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _GUIScrollbars_Generate
; Description ...: Generates scrollbars for a GUI with a defined aperture with proportional thumb sizes
; Syntax.........: _GUIScrollbars_Generate ($hWnd, $iH_Scroll = 0, [$iV_Scroll = 0, [$iH_Tight = 0, [$iV_Tight = 0, [$fBefore = False]]]])
; Parameters ....: $hWnd      -> GUI to contain scrollbars
;                  $iH_Scroll -> Width in pixels of area to be scrolled
;                  $iV_Scroll -> Height in pixels of area to be scrolled (default = 0)
;                  $iH_Tight  -> 1 = Adjust mean position of right edge of scrolled area to right (default = 0)
;                  $iV_Tight  -> 1 = Adjust mean position of bottom edge of scrolled area down (default = 0)
;                  $fBefore   -> True  = Scrollbars are being generated BEFORE controls
;                                False = Scrollbars are being generated AFTER controls (default)
; Requirement(s).: v3.3.6.0 or higher
; Return values .: Success - Returns a 4-element array (see remarks for details):
;                            [0] = Actual aperture width ; [1] = Actual aperture height]
;                            [2] = Width correction factor ; [3] = Height correction factor]
;                  Failure - Returns either 0 (UDF error) or negative integer (API error)
;                            If UDF error then @error set as follows:
;                               1 - hWnd not a valid handle
;                               2 - No scroll size parameters
;                               3 - Scrollbar creation or parameter setting failure
;                            If API error then @error and @extended as set by API error.  Return values:
;                               -1 - GetDC failure
;                               -2 - GetTextMetricsW failure
;                               -3 - GetClientRect failure
; Remarks .......; The $fBefore parameter is needed because of the way Windows deals with scrollbars.  When the
;                  scrollbars are generated, the visible part of the scrollable GUI resizes to fit the in the
;                  remaining (smaller) client area.
;                  - If the scrollbars are to be generated BEFORE any controls, the UDF shoudl be called with the
;                  $fBefore parameter set.  The new client size of the aperture window is returned so that
;                  controls can then be created using these values.
;                  - If controls have been created before the scrollbars are generated then the UDF should be
;                  called without the $fBefore parameter.  The correction factors returned can then be applied to
;                  any subsequent control positioning and sizing.  This is necessary because of the positions and
;                  sizes of existing controls will be slightly altered as the scrollbars are generated and the GUI
;                  resized.  Any controls created subsequently would therefore be slightly misplaced in relation
;                  to the existing ones unless the correction factors are used when positoning and sizing them.
;                  - If existing controls were fixed in place using GUICtrlResizing($GUI_DOCKALL) there is no need
;                  to apply the correction factors as the controls will not have moved with the GUI resizing.
; Author ........: Melba23 - with some code based on the WinAPI and GUIScrollBars includes
; Example........; Yes
;=====================================================================================================================
Func _GUIScrollbars_Generate($hWnd, $iH_Scroll = 0, $iV_Scroll = 0, $iH_Tight = 0, $iV_Tight = 0, $fBefore = False)

    ; Check if valid window handle
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If $aSB_WindowInfo[0][0] <> "" Then
        ReDim $aSB_WindowInfo[UBound($aSB_WindowInfo) + 1][8]
        ReDim $aSB_WindowInfoEx[UBound($aSB_WindowInfo) + 1][5]
    EndIf

    ; If no scroll sizes set, return error
    If $iH_Scroll = 0 And $iV_Scroll = 0 Then Return SetError(2, 0, 0)

    ; Confirm Tight values
    If $iH_Tight <> 0 Then $iH_Tight = 1
    If $iV_Tight <> 0 Then $iV_Tight = 1

    ; Create structs
    Local $tTEXTMETRIC = DllStructCreate($tagTEXTMETRIC)
    Local $tSCROLLINFO = DllStructCreate($tagSCROLLINFO)
    DllStructSetData($tSCROLLINFO, "cbSize", DllStructGetSize($tSCROLLINFO))
    Local $tRect = DllStructCreate($tagRECT)

    ; Declare local variables
    Local $iIndex = UBound($aSB_WindowInfo) - 1
    Local $iError, $iExtended

    ; Save window handle
    $aSB_WindowInfo[$iIndex][0] = $hWnd

    ; Determine text size
    Local $hDC = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hWnd)
    If Not @error Then
        $hDC = $hDC[0]
        DllCall("gdi32.dll", "bool", "GetTextMetricsW", "handle", $hDC, "ptr", DllStructGetPtr($tTEXTMETRIC))
        If @error Then
            $iError = @error
            $iExtended = @extended
            DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
            Return SetError($iError, $iExtended, -2)
        EndIf
        DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hWnd, "handle", $hDC)
    Else
        Return SetError(@error, @extended, -1)
    EndIf
    $aSB_WindowInfo[$iIndex][2] = DllStructGetData($tTEXTMETRIC, "tmAveCharWidth")
    $aSB_WindowInfo[$iIndex][3] = DllStructGetData($tTEXTMETRIC, "tmHeight") + DllStructGetData($tTEXTMETRIC, "tmExternalLeading")

    ; Size aperture window without bars
    DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    If @error Then Return SetError(@error, @extended, -3)
    Local $iX_Client_Full = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    Local $iY_Client_Full = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
    $aSB_WindowInfo[$iIndex][4] = $iX_Client_Full
    $aSB_WindowInfo[$iIndex][5] = $iY_Client_Full

    ; Register scrollbar and mousewheel messages
    GUIRegisterMsg($WM_VSCROLL, "_Scrollbars_WM_VSCROLL")
    GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")
    GUIRegisterMsg($WM_MOUSEWHEEL, "_Scrollbars_WM_MOUSEWHEEL")
    GUIRegisterMsg($WM_MOUSEHWHEEL, '_Scrollbars_WM_MOUSEHWHEEL')

    ; Show scrollbars
    _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, False)
    If $iH_Scroll Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ)
    If $iV_Scroll Then _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT)

    ; Size aperture window with bars
    DllCall("user32.dll", "bool", "GetClientRect", "hwnd", $hWnd, "ptr", DllStructGetPtr($tRect))
    If @error Then Return SetError(@error, @extended, -3)
    Local $iX_Client_Bar = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
    Local $iY_Client_Bar = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")

    ; If horizontal scrollbar is required
    Local $iH_FullPage
    If $iH_Scroll Then
        If $fBefore Then
            ; Use actual aperture width
            $aSB_WindowInfo[$iIndex][4] = $iX_Client_Bar
            ; Determine page size (aperture width / text width)
            $iH_FullPage = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
            ; Determine max size (scroll width / text width - tight)
            $aSB_WindowInfo[$iIndex][6] = Floor($iH_Scroll / $aSB_WindowInfo[$iIndex][2]) - $iH_Tight
        Else
            ; Use reduced aperture width only if other scrollbar exists
            If $iV_Scroll Then $aSB_WindowInfo[$iIndex][4] = $iX_Client_Bar
            ; Determine page size (aperture width / text width)
            $iH_FullPage = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
            ; Determine max size (scroll width / text width * correction factor for V scrollbar if required - tight)
            $aSB_WindowInfo[$iIndex][6] = Floor($iH_Scroll / $aSB_WindowInfo[$iIndex][2] * $aSB_WindowInfo[$iIndex][4] / $iX_Client_Full) - $iH_Tight
        EndIf
    Else
        $aSB_WindowInfo[$iIndex][6] = 0
    EndIf

    ; If vertical scrollbar required
    Local $iV_FullPage
    If $iV_Scroll Then
        If $fBefore Then
            ; Use actual aperture height
            $aSB_WindowInfo[$iIndex][5] = $iY_Client_Bar
            ; Determine page size (aperture width / text width)
            $iV_FullPage = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])
            ; Determine max size (scroll width / text width - tight)
            $aSB_WindowInfo[$iIndex][7] = Floor($iV_Scroll / $aSB_WindowInfo[$iIndex][3]) - $iV_Tight
        Else
            ; Use reduced aperture width only if other scrollbar exists
            If $iH_Scroll Then $aSB_WindowInfo[$iIndex][5] = $iY_Client_Bar
            ; Determine page size (aperture width / text width)
            $iV_FullPage = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])
            ; Determine max size (scroll width / text width * correction factor for H scrollbar if required - tight)
            $aSB_WindowInfo[$iIndex][7] = Floor($iV_Scroll / $aSB_WindowInfo[$iIndex][3] * $aSB_WindowInfo[$iIndex][5] / $iY_Client_Full) - $iV_Tight
        EndIf
    Else
        $aSB_WindowInfo[$iIndex][7] = 0
    EndIf

    Local $aRet[4]
    If $iV_Scroll Then
        $aRet[0] = $iX_Client_Bar
    Else
        $aRet[0] = $iX_Client_Full
    EndIf
    If $iH_Scroll Then
        $aRet[1] = $iY_Client_Bar
    Else
        $aRet[1] = $iY_Client_Full
    EndIf
    $aRet[2] = $iX_Client_Bar / $iX_Client_Full
    $aRet[3] = $iY_Client_Bar / $iY_Client_Full

    ; Save extended window info
    $aSB_WindowInfoEx[$iIndex][0] = $iH_Scroll
    $aSB_WindowInfoEx[$iIndex][1] = $iV_Scroll
    $aSB_WindowInfoEx[$iIndex][2] = $aRet[2]
    $aSB_WindowInfoEx[$iIndex][3] = $aRet[3]
    $aSB_WindowInfoEx[$iIndex][4] = $fBefore

    Local $fSuccess = True
    If _GUIScrollBars_ShowScrollBar($hWnd, $SB_BOTH, False) = False Then $fSuccess = False
    If $iH_Scroll Then
        If _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_HORZ, $aSB_WindowInfo[$iIndex][6]) = False Then $fSuccess = False
        _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_HORZ, $iH_FullPage)
        If @error Then $fSuccess = False
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, True) = False Then $fSuccess = False
    Else
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False) = False Then $fSuccess = False
    EndIf
    If $iV_Scroll Then
        If _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_VERT, $aSB_WindowInfo[$iIndex][7]) = False Then $fSuccess = False
        _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_VERT, $iV_FullPage)
        If @error Then $fSuccess = False
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, True) = False Then $fSuccess = False
    Else
        If _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, False) = False Then $fSuccess = False
    EndIf

    If $fSuccess Then Return $aRet
    Return SetError(3, 0, 0)

EndFunc   ;==>_GUIScrollbars_Generate

; #FUNCTION# =========================================================================================================
; Name...........: _GUIScrollbars_Locate_Ctrl
; Description ...: Calculates coordinates to use to position controls after scrollbar creation
; Syntax.........: _GUIScrollbars_Locate_Ctrl ($hWnd, $iX, $iY)
; Parameters ....: $hWnd -> GUI to contain control
;                  $iX   -> Horizontal coordinate relative to scrollable area
;                  $iY   -> Vertical coordinate relative to scrollable area
; Requirement(s).: v3.3.6.0 or higher
; Return values .: Success - Returns a 2-element array:
;                            [0] = Horizontal coordinate
;                            [1] = Vertical coordinate
;                  Failure - Returns either 0 with @error set as follows:
;                            1 - Invalid window handle
;                            2 - Parameter error
;                            3 - Window not found
; Remarks .......;
; Author ........: Melba23
; Example........; Yes
;=====================================================================================================================
Func _GUIScrollbars_Locate_Ctrl($hWnd, $iX, $iY)

    ; Check $hWnd
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)

    ; Find window info
    Local $iIndex = -1
    For $i = 0 To UBound($aSB_WindowInfo) - 1
        If $hWnd = $aSB_WindowInfo[$i][0] Then $iIndex = $i
    Next
    If $iIndex = -1 Then Return SetError(3, 0, 0)

    ; Check if location is within scrollable area of the window
    If $iX < 0 Or $iX > $aSB_WindowInfoEx[$iIndex][0] Then Return SetError(2, 0, 0)
    If $iY < 0 Or $iY > $aSB_WindowInfoEx[$iIndex][1] Then Return SetError(2, 0, 0)

    ; Calculate factored coordinates if needed
    If Not $aSB_WindowInfoEx[$iIndex][4] Then
        $iX *= $aSB_WindowInfoEx[$iIndex][2]
        $iY *= $aSB_WindowInfoEx[$iIndex][3]
    EndIf

    ; Correct for any scrollbar movement
    $iX -= _GUIScrollBars_GetScrollInfoPos($hWnd, $SB_HORZ) * $aSB_WindowInfo[$iIndex][2]
    $iY -= _GUIScrollBars_GetScrollInfoPos($hWnd, $SB_VERT) * $aSB_WindowInfo[$iIndex][3]

    Local $aRet[2] = [$iX, $iY]

    Return $aRet

EndFunc   ;==>_GUIScrollbars_Locate_Ctrl

; #FUNCTION# =========================================================================================================
; Name...........: _GUIScrollbars_Scroll_Page
; Description ...: Scrolls scrollbars generated by _GUIScrollbars_Generate to min, max or page number
; Syntax.........: _GUIScrollbars_Scroll_Page ($hWnd, [$iH_Scroll_Pos = -1, [$iV_Scroll_Pos = -1]])
; Parameters ....: $hWnd          -> GUI to contain scrollbars
;                  $iH_Scroll_Pos -> Horizontal age number:
;                                    0 = No change
;                                    1+ = Scroll to page number
;                                    If page number is over max pages, then scroll to max position
;                  $iV_Scroll_Pos -> As $iH_Scroll_Pos for vertical pages
; Requirement(s).: v3.3.6.0 or higher
; Return values .: None
; Remarks .......;
; Author ........: Melba23
; Example........; Yes
;=====================================================================================================================
Func _GUIScrollbars_Scroll_Page($hWnd, $iH_Scroll_Pos = 0, $iV_Scroll_Pos = 0)

    Local $iPos

    ; Check $hWnd
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)

    ; Check $iH/V_Scroll_Pos
    If Not (IsInt($iH_Scroll_Pos) And IsInt($iV_Scroll_Pos)) Then Return SetError(2, 0, 0)

    ; Find window info
    Local $iIndex = -1
    For $i = 0 To UBound($aSB_WindowInfo) - 1
        If $hWnd = $aSB_WindowInfo[$i][0] Then $iIndex = $i
    Next
    If $iIndex = -1 Then Return SetError(1, 0, 0)

    ; Get page sizes
    Local $iH_Page = Floor($aSB_WindowInfo[$iIndex][4] / $aSB_WindowInfo[$iIndex][2])
    Local $iV_Page = Floor($aSB_WindowInfo[$iIndex][5] / $aSB_WindowInfo[$iIndex][3])

    If $iH_Scroll_Pos > 0 Then
        $iPos = ($iH_Scroll_Pos - 1) * $iH_Page
        If $iPos > $aSB_WindowInfo[$iIndex][6] Then $iPos = $aSB_WindowInfo[$iIndex][6]
        _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_HORZ, $iPos)
    EndIf
    If $iV_Scroll_Pos > 0 Then
        $iPos = ($iV_Scroll_Pos - 1) * $iV_Page
        If $iPos > $aSB_WindowInfo[$iIndex][7] Then $iPos = $aSB_WindowInfo[$iIndex][7]
        _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, $iPos)
    EndIf

EndFunc   ;==>_GUIScrollbars_Scroll_Page

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_VSCROLL
; Description ...: GUIRegisterMsg procedure for vertical scrollbar
; Syntax ........: _Scrollbars_WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Taken from AutoIt Help file
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam)

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

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $yChar = $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

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_HSCROLL
; Description ...: GUIRegisterMsg procedure for horizontal scrollbar
; Syntax ........: _Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
; Return values .: None
; Author ........: Taken from AutoIt Help file
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)

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

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $xChar = $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

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_MOUSEWHEEL
; Description ...: GUIRegisterMsg procedure for vertical mouse wheel scroll
; Syntax ........: _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Based on code from MrCreator & Malkey
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn, $iDelta = BitShift($wParam, 16) ; Mouse wheel movement

    If BitAND($wParam, 0x0000FFFF) Then ; If Ctrl or Shft pressed move Horz scrollbar
        $iDirn = $SB_LINERIGHT
        If $iDelta > 0 Then $iDirn = $SB_LINELEFT
        For $i = 1 To 7
            _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
        Next
    Else ; Move Vert scrollbar
        $iDirn = $SB_LINEDOWN
        If $iDelta > 0 Then $iDirn = $SB_LINEUP
        _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEWHEEL

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _Scrollbars_WM_MOUSEHWHEEL
; Description ...: GUIRegisterMsg procedure for horizontal mouse wheel scroll
; Syntax ........: _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
; Return values .: None
; Author ........: Based on code from MSDN, MrCreator & Malkey
; Remarks .......: This function is used internally by _Scrollbars_Generate
; ===============================================================================================================================
Func _Scrollbars_WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = $SB_LINERIGHT
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINELEFT ; Mouse wheel movement
    For $i = 1 To 7
        _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
    Next

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEHWHEEL

Note that the function is only available when the scrollbars have been created using the _GUIScrollbars_Generate function within the UDF as the necessary parameters for the new function are stored within the UDF as the scrollbars are generated. The function has not been added to the _GUIScrollbars_Size UDF for the same reasons. However, I have altered the first _GUIScrollbars_Size example script to show how the user can make the corrections manually (as in the post above).

Zip file in first post updated.

M23

Hi Melba23,

I am sorry i was away coz of my exams,

This is great a change, specially _GUIScrollbars_Locate_Ctrl . Now its working as expected.Posted Image

thanks for your kind support , time & this great UDF Posted Image

Regards,

Digisoul

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

  • Moderators

Digisoul,

Glad you like it! :mellow:

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

  • 7 months later...

This UDF does make things a lot simpler, however I still get some strange effects. Perhaps that's something to do with windows. In the script below, I destroy the child GUI and recreate it each time to force new labels to be positioned correctly. Before I did this I occasionally got positioning problems on subsequent runs. The script adds a random number of labels and seems to work fine for small numbers. However if I change the random number of labels to between 1000 and above, things start to go wrong for me. $iRandom = Random(1000, 2000, 1)

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

_Main()

Func _Main()
    Local $GUIMsg, $hGUI, $h_cGUI

    $hGUI = GUICreate("ScrollBar Example", 400, 400)
    GUISetBkColor(0x88AABB, $hGUI)

    $hButton2 = GUICtrlCreateButton("Run", 10, 10, 90, 20)

    $h_cGUI = GUICreate("Child GUI", 380, 200, 8, 100, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)

    GUISetBkColor(0xFFFFFF, $h_cGUI)
    GUISetState()

    GUISwitch($hGUI)
    GUISetState()

    While 1
        $GUIMsg = GUIGetMsg()

        Switch $GUIMsg
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $hButton2
                GUIDelete($h_cGUI)

                $h_cGUI = GUICreate("Child GUI", 380, 200, 8, 100, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
                GUISetBkColor(0xFFFFFF)

                $iRandom = Random(100, 200, 1)
                Local $aLabels[$iRandom]
                $j = 0
                For $i = 1 To $iRandom -1
                    $aLabels[$i] = GUICtrlCreateLabel($i & @CRLF & "Hello World", 10, $j, 70, 40)
                    $j += 40
                Next
                _GUIScrollbars_Generate($h_cGUI, 0, ($iRandom -1)*40)
                GUISetState()
                MsgBox(0, "Random Number", $iRandom -1)
        EndSwitch
    WEnd

    Exit
EndFunc   ;==>_Main

I'm also getting intermittent problems with the mouse wheel. Every now and then (after about 10 mouse wheel scrolls) the labels shift left and sometimes disappear beyond the left border. This is most frustrating.

I just discovered that the problem is connected to clicking the mouse wheel button. It seems like a bug because I set the horizontal scroll value to zero.

If I comment out the following line, the horizontal shift problem seems to disappear.

Func _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn, $iDelta = BitShift($wParam, 16) ; Mouse wheel movement

    If BitAND($wParam, 0x0000FFFF) Then ; If Ctrl or Shft pressed move Horz scrollbar
        $iDirn = $SB_LINERIGHT
        If $iDelta > 0 Then $iDirn = $SB_LINELEFT
        For $i = 1 To 7
            ;_SendMessage($hWnd, $WM_HSCROLL, $iDirn) ; ==> THIS WAS CAUSING THE PROBLEM (I THINK)
        Next
    Else ; Move Vert scrollbar
        $iDirn = $SB_LINEDOWN
        If $iDelta > 0 Then $iDirn = $SB_LINEUP
        _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>_Scrollbars_WM_MOUSEWHEEL
Edited by czardas
Link to comment
Share on other sites

  • Moderators

czardas,

Try to help and look what you get - complaints! ;)

Both problems can be explained:

- 1. "things start to go wrong" because there seems to be a limit to the size of a GUI! :idiot:

If you run this modified code, you will see that you can never get above the following number of labels to display:

Height       Number     Height coord of final label
20           1639       32760
30           1093       32760
40            820       32760

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

_Main()

Func _Main()
    Local $GUIMsg, $hGUI, $h_cGUI = 9999

    $hGUI = GUICreate("ScrollBar Example", 400, 400)
    GUISetBkColor(0x88AABB, $hGUI)

    $hRadio_1 = GUICtrlCreateRadio(" 20 pixels",  10, 40, 100, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    $hRadio_2 = GUICtrlCreateRadio(" 30 pixels", 110, 40, 100, 20)
    $hRadio_3 = GUICtrlCreateRadio(" 40 pixels", 210, 40, 100, 20)

    $hButton2 = GUICtrlCreateButton("Run", 10, 10, 90, 20)

    GUISetState()

    While 1
        $GUIMsg = GUIGetMsg()

        Switch $GUIMsg
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $hButton2
                GUIDelete($h_cGUI)

                $iPixels = 20
                $iLabels = 1700
                If GUICtrlRead($hRadio_2) = 1 Then
                    $iPixels = 30
                    $iLabels = 1100
                EndIf
                If GUICtrlRead($hRadio_3) = 1 Then
                    $iPixels = 40
                    $iLabels = 850
                EndIf

                $h_cGUI = GUICreate("Child GUI", 380, 200, 8, 100, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
                GUISetBkColor(0xFFFFFF)


                Local $aLabels[$iLabels]
                For $i = 0 To $iLabels - 1
                    $aLabels[$i] = GUICtrlCreateLabel($i + 1 & " Hello World", 10, $i * $iPixels, 200, $iPixels)
                    GUICtrlSetBkColor(-1, 0xFF0000)
                Next
                _GUIScrollbars_Generate($h_cGUI, 0, $iLabels * $iPixels)
                GUISetState()
                MsgBox(0, "Label Number", $iLabels)
        EndSwitch
    WEnd

    Exit
EndFunc   ;==>_Main

The coordinate value for the final label looks suspiciously close to 32767 which is one of those magic numbers in computing - 0x7FFF - a 16-bit signed integer. As you specify the coordinates for a control in int form when you create it, I would be pretty confident in guessing that you cannot use values above 0x7FFF in the position and size parameters of a control. Thus, although you can create the controls, you cannot display them. :idiot:

So I firmly absolve my UDF of all blame and point the finger firmly at MS. It looks as if you will have to limit the number of labels you display - although I do have some sympathy with MS, trying to use 2000 labels is a bit out of the ordinary! :D

- 2. Here I put my hand up and accept that the problem is in the UDF. You can reproduce it at will by pressing Ctrl and moving the mouse wheel (which is the standard way for mice with no horizontal wheel to scroll in that sense). I have altered the UDF to only initiate the horizontal and vertical scrollbar and mouse wheel message handlers if the user asks for the relevant axis to be activated - that way they will not fire if no scrollbar is present in that axis. Thanks for finding that bug - although I would worry about your mouse because it looks as if its wheel cannot decide on which axis to work - I cannot get my vertical wheel to act horizontally without using the Ctrl key! :D

M23

Edit: Amended UDF and zip in first post. :)

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

  • 3 months later...

Melba23,

If the scrollbar positions are not at zero and you resize the widow then the positions are wrong afterwards and you might not be able to scroll to get the top left of the scrolled area into view.

Kip showed how to deal with this here

[link] [/link]

Edit: replaced my nasty suggestion for a fix with a link to Kip's excellent solution.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

  • Moderators

martin,

Could you please have a play with this and see if it deals adequately with resizeable GUIS? It uses the GUIScrollBars_Size UDF to reset/hide the scrollbars as the GUI is resized: ;)

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

Global Const $WM_ENTERSIZEMOVE = 0x231
Global $iScrollWidth = 1000, $iScrollHeight = 500

; Create resizeable GUI with red background
$hGUI = GUICreate("Test", 500, 500, -1, -1, BitOr($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX))
GUISetBkColor(0xFF0000, $hGUI)

; Create scrollbars before the controls
_GUIScrollbars_Generate($hGUI, $iScrollWidth, $iScrollHeight, 0, 0, True)

; Create a 1000x1000 green label
$hLabel = GUICtrlCreateLabel("", 0, 0, $iScrollWidth, $iScrollHeight)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlSetResizing($hLabel, $GUI_DOCKALL) ; If you do not fix the size then then there is little point!

GUISetState()

GUIRegisterMsg($WM_SIZE, "_WM_SIZE")

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


Func _WM_SIZE($hWnd, $iMsg, $wParam, $lParam)

    _Scrollbars_SIZE_Handler($hWnd, $iMsg, $wParam, $lParam)

EndFunc

Func _Scrollbars_SIZE_Handler($hWnd, $iMsg, $wParam, $lParam)

    ; Look through GUI list
    For $iIndex = 0 To UBound($aSB_WindowInfo) - 1
        ; Message comes from a GUI where scrollbars were generated by the UDF
        If $hWnd = $aSB_WindowInfo[$iIndex][0] Then
            ; Get new GUI size
            $iGUIWidth = BitAND($lParam, 0xFFFF)
            $iGUIHeight = BitShift($lParam, 16)
            ; Reset the scrollbars to top left
            _GUIScrollbars_Scroll_Page($hWnd, 1, 1)
            ; Check if GUI is larger than the scrollable area using data stored when the scrollbars were generated
            If $iGUIWidth >= $aSB_WindowInfoEx[$iIndex][0] Then $iGUIWidth = 0
            If $iGUIHeight >= $aSB_WindowInfoEx[$iIndex][1] Then $iGUIHeight = 0
            ; Get new Page and Max values
            $aRet = _GUIScrollbars_Size($aSB_WindowInfoEx[$iIndex][0], $aSB_WindowInfoEx[$iIndex][1], $iGUIWidth, $iGUIHeight)
            ; Reset or hide scrollbars
            If $iGUIWidth Then
                _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, True)
                _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_HORZ, $aRet[0])
                _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_HORZ, $aRet[1])
            Else
                _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False)
            EndIf
            If $iGUIHeight Then
                _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, True)
                _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_VERT, $aRet[2])
                _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_VERT, $aRet[3])
            Else
                _GUIScrollBars_ShowScrollBar($hWnd, $SB_VERT, False)
            EndIf
        EndIf
    Next

EndFunc

I think it is all self-explanatory. I have written it this way so that you can add the function to an existing WM_SIZE handler as I felt that if you were resizing a GUI you probably already had one! :D

And if anyone else has any comments, please share them. If it works as required I will release a new version with this included :>

jscript,

Thanks. :unsure:

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

martin,

Could you please have a play with this ....

Melba23,

Thanks for putting the time into this.

Yes, I do have a WM_SIZE handler.

Your example (previous post) isn't as I'd like it although it does do what I suggested earlier.

Suppose you scroll down vertically so that you have some control in view. Actually in the script I'm working on it's a drawing. When you stretch the window by grabbing the bottom right corner then as the viewed area increases you expect to see more in the increased area, but you want the top left to stay where it is. At least I do, although I know my suggestion didn't do that.

So I tried Kip's fix and it worked a treat so I changed my post #36 to give a link to his solution. I haven't studied your code so maybe you are already pretty close.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

  • Moderators

martin,

A new version which does reset the scrollbars after resizing - just move the blue box to the corner and resize: ;)

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

; ~~~~~~~~~~~~~~~~~~~~
; These will be in the UDF - Flag, HScroll Pos, VScroll Pos, HScroll Vis, $vScroll Vis - last 2 set by UDF when scrollbars generated
Global $aSB_ScrollInfo[5] = [0, 0, 0, True, True]
Global Const $WM_ENTERSIZEMOVE = 0x231
Global Const $WM_EXITSIZEMOVE = 0x232
; ~~~~~~~~~~~~~~~~~~~~

Global $iScrollWidth = 1000, $iScrollHeight = 1000

; Create resizeable GUI with red background
$hGUI = GUICreate("Test", 500, 500, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX))
GUISetBkColor(0xFF0000, $hGUI)

; Create scrollbars before the controls
_GUIScrollbars_Generate($hGUI, $iScrollWidth, $iScrollHeight, 0, 0, True)

; Create a 1000x1000 green label
$hLabel = GUICtrlCreateLabel("", 0, 0, $iScrollWidth, $iScrollHeight)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlSetResizing(-1, $GUI_DOCKALL) ; If you do not fix the size then then there is little point!

$hLabel_2 = GUICtrlCreateLabel("", 100, 100, 20, 20)
GUICtrlSetBkColor(-1, 0x0000FF)
GUICtrlSetResizing(-1, $GUI_DOCKALL)

GUISetState()

GUIRegisterMsg($WM_SIZE, "_Scrollbars_WM_SIZE")
GUIRegisterMsg($WM_ENTERSIZEMOVE, "_Scrollbars_WM_ENTERSIZEMOVE")
GUIRegisterMsg($WM_EXITSIZEMOVE, "_Scrollbars_WM_EXITSIZEMOVE")

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

Func _Scrollbars_WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam)

    ; Look through GUI list
    For $iIndex = 0 To UBound($aSB_WindowInfo) - 1
        ; Message comes from a GUI where scrollbars were generated by the UDF
        If $hWnd = $aSB_WindowInfo[$iIndex][0] Then
            ; Check it is Size event
            Switch MouseGetCursor()
                Case 8 To 13
                    ; Set Flag
                    $aSB_ScrollInfo[0] = $iIndex + 1
                    ; Get scrollbar positions if visible
                    If $aSB_ScrollInfo[3] Then
                        $aSB_ScrollInfo[1] = _GUIScrollBars_GetScrollPos($hWnd, $SB_HORZ)
                    Else
                        $aSB_ScrollInfo[1] = 0
                    EndIf
                    If $aSB_ScrollInfo[4] Then
                        $aSB_ScrollInfo[2] = _GUIScrollBars_GetScrollPos($hWnd, $SB_Vert)
                    Else
                        $aSB_ScrollInfo[2] = 0
                    EndIf
                    ; Set the scrollbars to top left
                    _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_HORZ, 0)
                    _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_Vert, 0)

            EndSwitch
        EndIf
    Next

EndFunc   ;==>_Scrollbars_WM_ENTERSIZEMOVE

Func _Scrollbars_WM_EXITSIZEMOVE($hWnd, $iMsg, $wParam, $lParam)

    ; If flag set
    If $aSB_ScrollInfo[0] Then
        ; Reset the scrollbars to the original position
        _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_HORZ, $aSB_ScrollInfo[1])
        _GUIScrollBars_SetScrollInfoPos($hWnd, $SB_Vert, $aSB_ScrollInfo[2])
        ; Reset flag
        $aSB_ScrollInfo[0] = 0
    EndIf
EndFunc   ;==>_Scrollbars_WM_EXITSIZEMOVE

Func _Scrollbars_WM_SIZE($hWnd, $iMsg, $wParam, $lParam)

    _Scrollbars_SIZE_Handler($hWnd, $iMsg, $wParam, $lParam)

EndFunc   ;==>_Scrollbars_WM_SIZE

Func _Scrollbars_SIZE_Handler($hWnd, $iMsg, $wParam, $lParam)

    ; Set correct GUI
    $iIndex = $aSB_ScrollInfo[0] - 1
    ; Get new GUI size
    $iGUIWidth = BitAND($lParam, 0xFFFF)
    $iGUIHeight = BitShift($lParam, 16)
    ; Store new values
    $aSB_WindowInfo[$iIndex][4] = $iGUIWidth
    $aSB_WindowInfo[$iIndex][5] = $iGUIHeight
    ; Check if GUI is larger than the scrollable area using data stored when the scrollbars were generated
    If $iGUIWidth >= $aSB_WindowInfoEx[$iIndex][0] Then $iGUIWidth = 0
    If $iGUIHeight >= $aSB_WindowInfoEx[$iIndex][1] Then $iGUIHeight = 0
    ; Get new Page and Max values
    $aRet = _GUIScrollbars_Size($aSB_WindowInfoEx[$iIndex][0], $aSB_WindowInfoEx[$iIndex][1], $iGUIWidth, $iGUIHeight)
    If Not @error Then
        ; Store new values
        $aSB_WindowInfo[$iIndex][6] = $aRet[1]
        $aSB_WindowInfo[$iIndex][7] = $aRet[3]
        ; Reset or hide scrollbars
        If $iGUIWidth Then
            ;_GUIScrollBars_SetScrollInfoPos($hWnd, $SB_HORZ, 0)
            _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, True)
            _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_HORZ, $aRet[0])
            _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_HORZ, $aRet[1])
            $aSB_ScrollInfo[3] = True
        Else
            _GUIScrollBars_ShowScrollBar($hWnd, $SB_HORZ, False)
            $aSB_ScrollInfo[3] = False
        EndIf
        If $iGUIHeight Then
            ;_GUIScrollBars_SetScrollInfoPos($hWnd, $SB_VERT, 0)
            _GUIScrollBars_ShowScrollBar($hWnd, $SB_Vert, True)
            _GUIScrollBars_SetScrollInfoPage($hWnd, $SB_Vert, $aRet[2])
            _GUIScrollBars_SetScrollInfoMax($hWnd, $SB_Vert, $aRet[3])
            $aSB_ScrollInfo[4] = True
        Else
            _GUIScrollBars_ShowScrollBar($hWnd, $SB_Vert, False)
            $aSB_ScrollInfo[4] = False
        EndIf
    EndIf

EndFunc   ;==>_Scrollbars_SIZE_Handler

I am still working on the resize part: if I do not set the scrollbars back into the top left corner then the scrollbar sizing and resetting messes up - if I do the the inner GUI is misplaced during the resize. :>

What do you think? Worth adding to the UDF? :unsure:

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

  • Melba23 changed the title to Scrollbars Made Easy - New version 27 Jan 22

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...