Jump to content

GUIScrollBars : scrollbar range


Go to solution Solved by MattyD,

Recommended Posts

Posted

 

Good evening, I hope you are all well,

 

Can someone help me to calculate the maximum horizontal scroll range?

"_GUIScrollBars_SetScrollInfoMax($hGuiScroll, $SB_HORZ, $iXpos - 550)"

 

Thanks in advance

 

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <GuiScrollBars.au3>
#include <ScrollBarsConstants.au3>


Local $iXpos = 10, $iButtonsCount = 20

$hGuiScroll = GUICreate("", 550, 70, -1, -1)
GUISetBkColor(0x212121, $hGuiScroll)
_GUIScrollBars_Init($hGuiScroll, 1000)
_GUIScrollBars_ShowScrollBar($hGuiScroll, $SB_VERT, False)

For $t = 1 To $iButtonsCount
    GUICtrlCreateButton($t, $iXpos, 5, 100, 28)
    $iXpos += 100
Next

_GUIScrollBars_SetScrollInfoMax($hGuiScroll, $SB_HORZ, $iXpos - 550)

GUISetState(@SW_SHOW, $hGuiScroll)

GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUIRegisterMsg($WM_HSCROLL, "__Scrollbars_WM_HSCROLL")

While 1
    Sleep(10)
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd


; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: __Scrollbars_WM_HSCROLL
; Description ...: Handler for horizontal scrollbar
; Syntax ........: __Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
; Return values .: None
; Author ........: Taken from AutoIt Help file
; Remarks .......:
; ===============================================================================================================================
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($__g_aSB_WindowInfo) - 1
        If $__g_aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $xChar = $__g_aSB_WindowInfo[$iIndex][2]
            ExitLoop
        EndIf
    Next
    If $iIndex = -1 Then Return 0

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

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

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

    Return $GUI_RUNDEFMSG
EndFunc   ;==>__Scrollbars_WM_HSCROLL


Func WM_NCHITTEST($hWnd, $iMsg, $wParam, $lParam)
    Local $iRet = _WinAPI_DefWindowProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $iRet
        Case $HTVSCROLL
            Return $HTVSCROLL
        Case $HTHSCROLL
            Return $HTHSCROLL
        Case Else
            Return $HTCLIENT
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NCHITTEST

 

  • Solution
Posted (edited)

Hey mate,

I could have this wrong, but from a bit of reading the distance of a scroll unit depends on line widths/heights. Presumably this is why _GuiScrollBars_Init() does something like this.

$hGuiScroll = GUICreate("", 550, 70, -1, -1)
Local $aCall = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hGuiScroll)
$hDC = $aCall[0]
Local $tTEXTMETRIC = DllStructCreate($tagTEXTMETRIC)
DllCall("gdi32.dll", "bool", "GetTextMetricsW", "handle", $hDC, "struct*", $tTEXTMETRIC)

Local $iXAmount = DllStructGetData($tTEXTMETRIC, "tmAveCharWidth")
Local $iYAmount = DllStructGetData($tTEXTMETRIC, "tmHeight") + DllStructGetData($tTEXTMETRIC, "tmExternalLeading")
ConsoleWrite($iXAmount & @CRLF)
ConsoleWrite($iYAmount & @CRLF)
DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hGuiScroll, "handle", $hDC)

I'm assuming these are the values for scrolling by "line", then a "page" is set to a multiple of this.

According to MS The max scroll position is:

MaxScrollPos = MaxRangeValue - (PageSize - 1)

So if I have this right...

$iClW = _WinAPI_GetClientWidth($hGuiScroll)
$iFullW = $iButtonsCount * $iBtnW + 2 * $iMar
$iPageW = _GUIScrollBars_GetScrollInfoPage($hGuiScroll, $SB_HORZ)
$iMaxValRng = Int(($iFullW-$iClW)/$iXAmount)
$iMaxScrollPos = $iMaxValRng + ($iPageW - 1)

_GUIScrollBars_SetScrollInfoMax($hGuiScroll, $SB_HORZ, $iMaxScrollPos)
_GUIScrollBars_SetScrollInfoMin($hGuiScroll, $SB_HORZ, 0)

Edit: and here's something that is run-able ;)

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <GuiScrollBars.au3>
#include <ScrollBarsConstants.au3>

$hGuiScroll = GUICreate("", 550, 70, -1, -1)
Local $aCall = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hGuiScroll)
$hDC = $aCall[0]
Local $tTEXTMETRIC = DllStructCreate($tagTEXTMETRIC)
DllCall("gdi32.dll", "bool", "GetTextMetricsW", "handle", $hDC, "struct*", $tTEXTMETRIC)

Local $iXAmount = DllStructGetData($tTEXTMETRIC, "tmAveCharWidth")
Local $iYAmount = DllStructGetData($tTEXTMETRIC, "tmHeight") + DllStructGetData($tTEXTMETRIC, "tmExternalLeading")
DllCall("user32.dll", "int", "ReleaseDC", "hwnd", $hGuiScroll, "handle", $hDC)

GUISetBkColor(0x212121, $hGuiScroll)
_GUIScrollBars_Init($hGuiScroll, 1000)
_GUIScrollBars_ShowScrollBar($hGuiScroll, $SB_VERT, False)

Local $iBtnW = 100, $iMar = 10
Local $iXpos = $iMar, $iButtonsCount = 20

For $t = 1 To $iButtonsCount
    GUICtrlCreateButton($t, $iXpos, 5, $iBtnW, 28)
    $iXpos += $iBtnW
Next

$iClW = _WinAPI_GetClientWidth($hGuiScroll)
$iFullW = $iButtonsCount * $iBtnW + 2 * $iMar
$iPageW = _GUIScrollBars_GetScrollInfoPage($hGuiScroll, $SB_HORZ)
$iMaxValRng = Round(($iFullW-$iClW)/$iXAmount)
$iMaxScrollPos = $iMaxValRng + ($iPageW - 1)

ConsoleWrite(StringFormat("%20s: %-4d %20s: %-4d", "HScrollUnit", $iXAmount, "HPageSize", $iPageW) & @CRLF)
ConsoleWrite(StringFormat("%20s: %-4d %20s: %-4d", "ClientWidth", $iClW, "FullFormWidth", $iFullW) & @CRLF)
ConsoleWrite(StringFormat("%20s: %-4d %20s: %-4d", "MaxHRangeValue", $iMaxValRng, "MaxHScrollPos", $iMaxScrollPos) & @CRLF)

_GUIScrollBars_SetScrollInfoMax($hGuiScroll, $SB_HORZ, $iMaxScrollPos)
_GUIScrollBars_SetScrollInfoMin($hGuiScroll, $SB_HORZ, 0)

GUISetState(@SW_SHOW, $hGuiScroll)

GUIRegisterMsg($WM_NCHITTEST, "WM_NCHITTEST")
GUIRegisterMsg($WM_HSCROLL, "__Scrollbars_WM_HSCROLL")

While 1
    Sleep(10)
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd


; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: __Scrollbars_WM_HSCROLL
; Description ...: Handler for horizontal scrollbar
; Syntax ........: __Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
; Return values .: None
; Author ........: Taken from AutoIt Help file
; Remarks .......:
; ===============================================================================================================================
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($__g_aSB_WindowInfo) - 1
        If $__g_aSB_WindowInfo[$x][0] = $hWnd Then
            $iIndex = $x
            $xChar = $__g_aSB_WindowInfo[$iIndex][2]
            ExitLoop
        EndIf
    Next
    If $iIndex = -1 Then Return 0

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

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

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

    Return $GUI_RUNDEFMSG
EndFunc   ;==>__Scrollbars_WM_HSCROLL


Func WM_NCHITTEST($hWnd, $iMsg, $wParam, $lParam)
    Local $iRet = _WinAPI_DefWindowProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $iRet
        Case $HTVSCROLL
            Return $HTVSCROLL
        Case $HTHSCROLL
            Return $HTHSCROLL
        Case Else
            Return $HTCLIENT
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NCHITTEST
Edited by MattyD
Posted

My pleasure :) Just a couple of extra tidbits I've found while having a play...

Those base scroll unit values can be found in $__g_aSB_WindowInfo. So you don't want to re-calculate - first do a  _GUIScrollBars_Init(), then just cycle through the array until you find your window handle.

$__g_aSB_WindowInfo[$iIndex][0] = $hWnd
$__g_aSB_WindowInfo[$iIndex][2] = $iHScrollUnit
$__g_aSB_WindowInfo[$iIndex][3] = $iVScrollUnit

The other thing I found was that the _WinAPI_GetClientWidth() and _WinAPI_GetClientHeight() values will change depending on if you're displaying a scroll bar.  This is a good thing. If the vertical bar is showing, the overall width will shrink accordingly to accommodate whatever real estate was lost. 

But the take away is: make sure the the vertical/horizontal bars are in the correct visibility state before you take your measurements.

Hope that makes sense!

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
  • Recently Browsing   0 members

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