Что нового

[Элементы GUI] Есть ли способ проматывания большого количества контролов?

kasper_sky

Antivirus
Сообщения
116
Репутация
1
Доброго времени суток.

Итак, у меня есть большое количество контролов(допустим, элементов Label), которое не помещается в окно GUI. Можно ли создать какую-нибудь перемотку контролов(например, вертикальную)?

P.S. Иные элементы(вроде ListView и т.д.) со стандартным скроллом не особо интересуют(специфика выполнения оформления GUI).

За код сильно не пинайте..
Элементы для "скроллинга" будут размещаться в левой части GUI, как первые три лэйбла.
Код:
#include <StaticConstants.au3>
#include <GUIConstants.au3>
#include <WinAPI.au3>

Const $iContactCtrlHeight = 23		; Cannot be lower than 18
Const $iContactCtrlDistance = 4
Const $iWidth = 170

Const $clSelectedContact = 0x4f739a
Const $clHoverContact = 0xe1e7ed
Const $clNewMessageContact = 0x9040A0
Const $clNormalContact = $GUI_BKCOLOR_TRANSPARENT
Const $clSelectedContactFont = 0xFFFFFF
Const $clNormalContactFont = 0x000000

Global $iFirstH = _CntFirstH()
Global $iMainH = _CntMainH()
Local $posY = $iContactCtrlDistance

Global $ahContacts[3][2]

Global $iContactsCtrlHover = 999999999999, $iContactsCtrlActive = -1



$hVkGUI = GuiCreate('VK | 1 новое сообщение', 800, 500)
GUISetFont(11)

; Separator
GUICtrlCreateLabel('', 179, 0, 1, 500)
GUICtrlSetBkColor(-1, 0x909090)

; Main photo
$hMainPic = GUICtrlCreatePic('', $iWidth + 16, 4, 50, 50)

; Main name label
Global $hNameLabel = GUICtrlCreateLabel('', $iWidth + 72, 2, (800 - $iWidth - 80), 26)
GUICtrlSetFont(-1, 18)
GUICtrlSetColor(-1, 0x1B486A)
;~ GUICtrlSetBkColor(-1, 0xFF0000)

; Secondary name label
Global $hNameLabel2 = GUICtrlCreateLabel('', $iWidth + 73, 28, (800 - $iWidth - 80), 16)
GUICtrlSetColor(-1, 0x97A5B5)
;~ GUICtrlSetBkColor(-1, 0xFF00F0)

$ahContacts[0][0] = GUICtrlCreateLabel('', 4, $posY, $iWidth, $iFirstH)
GUICtrlSetBkColor(-1, $clNormalContact)
	$posY += $iFirstH
$ahContacts[0][1] = GUICtrlCreateLabel('Zero Contact', 4, $posY, $iWidth, $iMainH, $SS_CENTER)
GUICtrlSetBkColor(-1, $clNormalContact)
	$posY += $iMainH

$posY += $iContactCtrlDistance

$ahContacts[1][0] = GUICtrlCreateLabel('', 4, $posY, $iWidth, $iFirstH)
GUICtrlSetBkColor(-1, $clNormalContact)
	$posY += $iFirstH
$ahContacts[1][1] = GUICtrlCreateLabel('First Contact', 4, $posY, $iWidth, $iMainH, $SS_CENTER)
GUICtrlSetBkColor(-1, $clNormalContact)
	$posY += $iMainH

$posY += $iContactCtrlDistance

$ahContacts[2][0] = GUICtrlCreateLabel('', 4, $posY, $iWidth, $iFirstH)
GUICtrlSetBkColor(-1, $clNormalContact)
	$posY += $iFirstH
$ahContacts[2][1] = GUICtrlCreateLabel('Second Contact', 4, $posY, $iWidth, $iMainH, $SS_CENTER)
GUICtrlSetBkColor(-1, $clNormalContact)

GUISetState()

;~ $hTimer = TimerInit()

Do
;~ 	If TimerDiff($hTimer) > 10000 Then
;~ 		$hTimer = TimerInit()

;~ 		GUICtrlSetBkColor($ahContacts[2][0], $clNewMessageContact)
;~ 		GUICtrlSetBkColor($ahContacts[2][1], $clNewMessageContact)

;~ 		GUICtrlSetColor($ahContacts[2][1], $clSelectedContactFont)
;~ 	EndIf

	$msg = GUIGetMsg()
	$aCursorInfo = GUIGetCursorInfo()

	; Hover func
	If IsArray($aCursorInfo) Then
		For $cnt = 0 To (UBound($ahContacts) - 1) Step 1
			If $aCursorInfo[4] = $ahContacts[$cnt][0] Or $aCursorInfo[4] = $ahContacts[$cnt][1] Then
				If $iContactsCtrlHover <> $cnt Then
					If $iContactsCtrlHover <> 999999999999 And $iContactsCtrlHover <> $iContactsCtrlActive Then
						GUICtrlSetBkColor($ahContacts[$iContactsCtrlHover][0], $clNormalContact)
						GUICtrlSetBkColor($ahContacts[$iContactsCtrlHover][1], $clNormalContact)
					EndIf

					If $cnt <> $iContactsCtrlActive Then
						GUICtrlSetBkColor($ahContacts[$cnt][0], $clHoverContact)
						GUICtrlSetBkColor($ahContacts[$cnt][1], $clHoverContact)

						GUICtrlSetColor($ahContacts[$cnt][1], $clNormalContactFont)
					EndIf

					$iContactsCtrlHover = $cnt
				EndIf
			ElseIf $aCursorInfo[4] = 0 Then
				If $iContactsCtrlHover <> 999999999999 And $iContactsCtrlHover <> $iContactsCtrlActive Then
					GUICtrlSetBkColor($ahContacts[$iContactsCtrlHover][0], $clNormalContact)
					GUICtrlSetBkColor($ahContacts[$iContactsCtrlHover][1], $clNormalContact)

					$iContactsCtrlHover = 999999999999
				EndIf
			EndIf
		Next
	EndIf

	; Select func
	For $cnt = 0 To (UBound($ahContacts) - 1) Step 1
		If $msg = $ahContacts[$cnt][0] Or $msg = $ahContacts[$cnt][1] Then
;~ 			ConsoleWrite(@CRLF & '! $cnt = ' & $cnt & @CRLF)
;~ 			ConsoleWrite('! $iContactsCtrlActive = ' & $iContactsCtrlActive & @CRLF)

			If $iContactsCtrlActive <> -1 Then
				GUICtrlSetBkColor($ahContacts[$iContactsCtrlActive][0], $clNormalContact)
				GUICtrlSetBkColor($ahContacts[$iContactsCtrlActive][1], $clNormalContact)

				GUICtrlSetColor($ahContacts[$iContactsCtrlActive][1], $clNormalContactFont)
			EndIf

			GUICtrlSetBkColor($ahContacts[$cnt][0], $clSelectedContact)
			GUICtrlSetBkColor($ahContacts[$cnt][1], $clSelectedContact)

			GUICtrlSetColor($ahContacts[$cnt][1], $clSelectedContactFont)
			$iContactsCtrlActive = $cnt

			_ShowDialog($cnt)
		EndIf
	Next

Until $msg = -3








Func _CntFirstH()
	$iHeight = $iContactCtrlHeight
	$iHeight -= 16
	$iHeight /= 2
	Return Floor($iHeight)
EndFunc


Func _CntMainH()
	$iHeight = $iContactCtrlHeight
	$iHeight -= 16
	$iHeight /= 2
	Return Round($iHeight) + 16
EndFunc


Func _ShowDialog($iNum)
	Switch $iNum
		Case 0
			GUICtrlSetData($hNameLabel, 'Нулевой контакт')
			GUICtrlSetData($hNameLabel2, 'В поиске...')
			GUICtrlSetImage($hMainPic, '')
		Case 1
			GUICtrlSetData($hNameLabel, 'Первый контакт')
			GUICtrlSetData($hNameLabel2, 'Онлайн')
;~ 			GUICtrlSetImage($hMainPic, @DesktopDir & '\1.jpg')
		Case 2
			GUICtrlSetData($hNameLabel, 'Второй контакт')
			GUICtrlSetData($hNameLabel2, 'Печатает...')
;~ 			GUICtrlSetImage($hMainPic, @DesktopDir & '\2.jpg')
		Case Else
			;
	EndSwitch
EndFunc
 

Findoss

Знающий
Сообщения
9
Репутация
7
Отличный пример от всеми любимого CreatoRа :ok:
http://autoit-script.ru/index.php/topic,641.msg4434.html#msg4434
Код:
#Region Includes
#include <ScrollBarConstants.au3>
#include <StructureConstants.au3>
#include <Array.au3>
#include <Date.au3>
#include <GuiScrollBars.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#EndRegion Includes

Opt("TrayIconDebug", 0)
Opt("OnExitFunc", "_Close")
;OnAutoItExitRegister("_Close")

#NoTrayIcon

Global $DebugModeStyle
Global $DebugMode_Style            = 1
If $DebugMode_Style = 1 Then $DebugModeStyle = $WS_BORDER

Global $fSize[7] = [10, 11, 12, 13, 14, 28, 38], $ffTahoma = "Tahoma"
Global $fwNormal = 400, $fwBold = 800, $fsNormal = 0, $fsItalic = 2
Global $cRed   = 0xFF0000, $cBlue  = 0x0000FF, $cGrey   = 0xDADBDD, $cGreen     = 0x008000
Global $cWhite = 0xFFFFFF, $cBlack = 0x000000, $cYellow = 0xFFFF00, $cLightGrey = 0x808080

Global $GUIWidth     = @DesktopWidth, $GUIHeight = @DesktopHeight, $GUILeft = -1, $GUITop  = -1, $GUIbgColor = $cGrey, $GUIHeightCor = 0
Global $SectionWidth = $GUIWidth, $SectionHeight = $GUIHeight - 150

$hForm = GUICreate("Form", $GUIWidth, $GUIHeight, $GUILeft, $GUITop)
GUISetBkColor($GUIbgColor)

GUICtrlCreateLabel("F  O   R   M", 205, 5, $GUIWidth - 205, 65, BitOr($SS_CENTER, $SS_CENTERIMAGE, $DebugModeStyle))
GUICtrlSetFont(-1, $fSize[6], $fwBold, $fsNormal, $ffTahoma)
GUICtrlSetColor(-1, $cBlue)

;GUIRegisterMsg($WM_SIZE, "WM_SIZE")
GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL")
GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")

GUISetState(@SW_SHOW, $hForm)

_DateTable()

While 1
    $FormMsg = GUIGetMsg()

    If $FormMsg = $GUI_EVENT_CLOSE Then _Close()
WEnd

Func _DateTable()
    Local $sDatesList = @DesktopDir & "\DatesList.ini"

    $aPersonalList = IniReadSectionNames($sDatesList)

    Local $iDTHeadLeft = 0, $iDTHeadTop = 100, $iDTHeadWidth = $SectionWidth, $iDTHeadHeight = $SectionHeight, $GUIbgColor = $cGrey
    $hDTHead = GUICreate("Date Table Header", $iDTHeadWidth, $iDTHeadHeight, $iDTHeadLeft, $iDTHeadTop, $WS_CHILD, -1, $hForm)
    GUISetBkColor($GUIbgColor)

    Local $iHeadLeft = 5, $iHeadTop = 5, $iHeadWidth = 210, $iHeadHeighth = 105
    Local $iHeadStyle = BitOr($SS_CENTER, $SS_CENTERIMAGE, $DebugModeStyle)
    GUICtrlCreateLabel("Имя", $iHeadLeft, $iHeadTop, $iHeadWidth, $iHeadHeighth, $iHeadStyle)
    GUICtrlSetBkColor(-1, $cRed)
    GUICtrlSetFont(-1, $fSize[0], $fwBold, $fsNormal, $ffTahoma)
    GUICtrlCreateLabel("Дата", $iHeadLeft + 210, $iHeadTop, $iHeadWidth * 4 + 50, $iHeadHeighth, $iHeadStyle)
    GUICtrlSetBkColor(-1, $cBlue)
    GUICtrlSetFont(-1, $fSize[0], $fwBold, $fsNormal, $ffTahoma)
    
    ;test
    GUICtrlCreateLabel("Тест", $iHeadLeft + 210 + ($iHeadWidth * 4 + 50), $iHeadTop, $iHeadWidth * 4 + 50, $iHeadHeighth, $iHeadStyle)
    
    GUICtrlSetBkColor(-1, $cBlue)
    GUICtrlSetFont(-1, $fSize[0], $fwBold, $fsNormal, $ffTahoma)
    
    Local $iDTBodyLeft = 0, $iDTBodyTop = 110, $iDTBodyWidth = $iDTHeadWidth, $iDTBodyHeight = $iDTHeadHeight - $iDTBodyTop, $GUIbgColor = $cGrey
    $hDTBody = GUICreate("Date Table Body", $iDTBodyWidth, $iDTBodyHeight, $iDTBodyLeft, $iDTBodyTop, $WS_CHILD + $WS_VSCROLL, -1, $hDTHead)
    GUISetBkColor($GUIbgColor)

    Local $iPLLeft = 5, $iPLTop = 0, $iPLWidth = 210, $iPLHeight = 30
    For $p = 1 To $aPersonalList[0]
        GUICtrlCreateLabel(" " & $aPersonalList[$p], $iPLLeft, $iPLTop, $iPLWidth, $iPLHeight, BitOr($SS_CENTERIMAGE, $DebugModeStyle))
        GUICtrlSetBkColor(-1, $cYellow)
        GUICtrlSetFont(-1, $fSize[0], $fwBold, $fsNormal, $ffTahoma)

        $iDate = IniRead($sDatesList, $aPersonalList[$p], "Date", "NA")
        GUICtrlCreateLabel($iDate, $iPLLeft + 210, $iPLTop, $iPLWidth * 4 + 50, $iPLHeight, BitOr($SS_CENTER, $SS_CENTERIMAGE, $DebugModeStyle))
        GUICtrlSetBkColor(-1, $cGreen)
        GUICtrlSetFont(-1, $fSize[0], $fwBold, $fsNormal, $ffTahoma)

        $iPLTop += 30
    Next
    
    _GUIScrollBars_Init($hDTBody, 0, 0)
    _GUIScrollBars_Init($hDTHead, 0, 0)
    _GUIScrollBars_SetScrollInfoMax($hDTBody, 0, 0)
    _GUIScrollBars_SetScrollInfoMax($hDTBody, 1, Round($aPersonalList[0] * 1.84))
    _GUIScrollBars_SetScrollInfoMax($hDTHead, 0, $iPLWidth)
    _GUIScrollBars_SetScrollInfoMax($hDTHead, 1, 0)
    
    GUISetState(@SW_SHOW, $hDTHead)
    GUISetState(@SW_SHOW, $hDTBody)

    GUISetState(@SW_SHOW, $hForm)
EndFunc   ;==>_PPC

Func WM_SIZE($hWnd, $Msg, $wParam, $lParam)
    #forceref $Msg, $wParam
    Local $index = -1, $yChar, $xChar, $xClientMax, $xClient, $yClient, $ivMax
    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $index = $x
            $xClientMax = $aSB_WindowInfo[$index][1]
            $xChar = $aSB_WindowInfo[$index][2]
            $yChar = $aSB_WindowInfo[$index][3]
            $ivMax = $aSB_WindowInfo[$index][7]
            ExitLoop
        EndIf
    Next
    If $index = -1 Then Return 0

    Local $tSCROLLINFO = DllStructCreate($tagSCROLLINFO)
    
    ; Retrieve the dimensions of the client area.
    $xClient = BitAND($lParam, 0x0000FFFF)
    $yClient = BitShift($lParam, 16)
    $aSB_WindowInfo[$index][4] = $xClient
    $aSB_WindowInfo[$index][5] = $yClient
    
    ; Set the vertical scrolling range and page size
    DllStructSetData($tSCROLLINFO, "fMask", BitOR($SIF_RANGE, $SIF_PAGE))
    DllStructSetData($tSCROLLINFO, "nMin", 0)
    DllStructSetData($tSCROLLINFO, "nMax", $ivMax)
    DllStructSetData($tSCROLLINFO, "nPage", $yClient / $yChar)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    
    ; Set the horizontal scrolling range and page size
    DllStructSetData($tSCROLLINFO, "fMask", BitOR($SIF_RANGE, $SIF_PAGE))
    DllStructSetData($tSCROLLINFO, "nMin", 0)
    DllStructSetData($tSCROLLINFO, "nMax", 2 + $xClientMax / $xChar)
    DllStructSetData($tSCROLLINFO, "nPage", $xClient / $xChar)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_SIZE

Func WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
    #forceref $Msg, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)

    Local $index = -1, $xChar, $xPos
    Local $Min, $Max, $Page, $Pos, $TrackPos

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $index = $x
            $xChar = $aSB_WindowInfo[$index][2]
            ExitLoop
        EndIf
    Next
    If $index = -1 Then Return 0
    
;~  ; Get all the horizontal scroll bar information
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    ; Save the position for comparison later on
    $xPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $xPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
    #forceref $Min, $Max
    Switch $nScrollCode

        Case $SB_LINELEFT ; user clicked left arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)

        Case $SB_LINERIGHT ; user clicked right arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)

        Case $SB_PAGELEFT ; user clicked the scroll bar shaft left of the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)

        Case $SB_PAGERIGHT ; user clicked the scroll bar shaft right of the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)

        Case $SB_THUMBTRACK ; user dragged the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

;~    // Set the position and then retrieve it.  Due to adjustments
;~    //   by Windows it may not be the same as the value set.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
    ;// If the position has changed, scroll the window and update it
    $Pos = DllStructGetData($tSCROLLINFO, "nPos")
    If ($Pos <> $xPos) Then _GUIScrollBars_ScrollWindow($hWnd, $xChar * ($xPos - $Pos), 0)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HSCROLL

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

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

    ; Get all the vertial scroll bar information
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx ($hWnd, $SB_VERT)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    ; Save the position for comparison later on
    $yPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $yPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")

    Switch $nScrollCode
        Case $SB_TOP; user clicked the HOME keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Min)

        Case $SB_BOTTOM; user clicked the END keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Max)

        Case $SB_LINEUP; user clicked the top arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)

        Case $SB_LINEDOWN; user clicked the bottom arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)

        Case $SB_PAGEUP; user clicked the scroll bar shaft above the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)

        Case $SB_PAGEDOWN; user clicked the scroll bar shaft below the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)

        Case $SB_THUMBTRACK; user dragged the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

;~    // Set the position and then retrieve it.  Due to adjustments
;~    //   by Windows it may not be the same as the value set.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo ($hWnd, $SB_VERT, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo ($hWnd, $SB_VERT, $tSCROLLINFO)
    ;// If the position has changed, scroll the window and update it
    $Pos = DllStructGetData($tSCROLLINFO, "nPos")

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

    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_VSCROLL

Func _Close()
    Exit
EndFunc   ;==>_Close

Вот можно и такой вариант , с раскладкой
p.s. Автор кода, здесь на форуме , но затерялся.
Код:
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <ButtonConstants.au3>

$hGUI = GUICreate('Test', 640, 480, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX))
$iLeft = 5 ; отступ слева
$iTop = 5 ; сверху
$iWidth = 150 ; общая ширина панели
$iHeight = 470 ; общаяя высота панели
$iButtonHeight = 25 ; высота кнопок групп
$iNumOfButtons = 6 ; количество групп
$sButtons = 'Files|Options|Media|Tools|Docs|Other' ; названия групп
$aButtonsNames = StringSplit($sButtons, '|', 2) ; перевод названия групп из строки в массив
If UBound($aButtonsNames) <> $iNumOfButtons Then ; проверка на равное количество индексов массивов
    SetError(1)
    Exit
EndIf
GUICtrlCreateGroup('', $iLeft, $iTop, $iWidth, $iHeight) ; рамка панели
GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKWIDTH) ; прилепить к левому краю, и запретить менять ширину панели
Dim $b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8, $b9, $b10, $b11, $b12, $b13, $b14, $b15, $b16, $b17, $b18, $b19, $b20, $b21 ; кнопки для наполнения панели
For $n = 1 To 21
    Assign('b' & $n, GUICtrlCreateButton($n, $iLeft, $iTop))
    GUICtrlSetState(Eval('b' & $n), $GUI_HIDE) ; прячем кнопки до их вызова через пункт на панели
    GUICtrlSetResizing(Eval('b' & $n), $GUI_DOCKLEFT + $GUI_DOCKTOP + $GUI_DOCKSIZE) ; прилепить к левому и верхнему краям, запретить менять размер
Next
Dim $aSpoiler0[3] = [$b1, $b2, $b3] ; формирование кнопок по группам
Dim $aSpoiler1[3] = [$b4, $b5, $b6]
Dim $aSpoiler2[3] = [$b7, $b8, $b9]
Dim $aSpoiler3[3] = [$b10, $b11, $b12]
Dim $aSpoiler4[3] = [$b13, $b14, $b15]
Dim $aSpoiler5[6] = [$b16, $b17, $b18, $b19, $b20, $b21]

Dim $aButtons[$iNumOfButtons]
For $i = 0 To UBound($aButtons) - 1  ; создание кнопок групп на панели
    If $i = 0 Then ; для первой группы
        $aButtons[$i] = GUICtrlCreateButton($aButtonsNames[$i], $iLeft, $iTop, $iWidth, $iButtonHeight, $BS_FLAT)
        GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKTOP + $GUI_DOCKSIZE) ; прилепить к левому и верхнему краям, запретить менять размер
        For $m = 0 To UBound($aSpoiler0) - 1 ; расстановка кнопок группы под ней
            GUICtrlSetPos($aSpoiler0[$m], $iLeft + 5, $iTop + $iButtonHeight + 5 + $m*25, $iWidth - 10, $iButtonHeight - 4)
            GUICtrlSetState($aSpoiler0[$m], $GUI_SHOW) ; отображаем
        Next
    Else  ; остальные кнопки групп размещаем внизу панели и прикрепляем к левому и нижнему краям + заперт на изменение размеров
        $aButtons[$i] = GUICtrlCreateButton($aButtonsNames[$i], $iLeft, $iHeight + $iTop - (UBound($aButtons) - $i)*$iButtonHeight, $iWidth, $iButtonHeight, $BS_FLAT)
        GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKBOTTOM + $GUI_DOCKSIZE)
    EndIf
Next

$aPos = WinGetPos($hGUI)
$iBottom = $aPos[3] - $iTop - $iHeight ; получение отступа между дном панели и нижним краем окна
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case -3
            Exit
    EndSwitch
    For $j = 0 To UBound($aButtons) - 1 ; нажатие кнопок группы
        If $msg = $aButtons[$j] Then
            $aPos = WinGetPos($hGUI) ; замеряем окное - на случай если его растягивали или сжимали
            For $u = 0 To $j ; все кнопки групп которые находятся выше нажатой и её саму ...
                GUICtrlSetPos($aButtons[$u], $iLeft, $iTop + $u*$iButtonHeight) ; перемещаем вверх панели
                GUICtrlSetResizing($aButtons[$u], $GUI_DOCKLEFT + $GUI_DOCKTOP + $GUI_DOCKSIZE) ; прикрепляем к левому и верхнему краям + запрет изменений размера
                For $n = 1 To 21 ; прячем все кнопки вложений
                    GUICtrlSetState(Eval('b' & $n), $GUI_HIDE)
                Next
                If $u = $j Then ; отображаем только кнопки, вложенные в нажатую группу, и перемещаем
                    For $q = 0 To UBound(Eval('aSpoiler' & $j)) - 1
                        GUICtrlSetPos(Execute('$aSpoiler' & $j & '[' & $q & ']'), $iLeft + 5, $iTop + $iButtonHeight*$j + $iButtonHeight + 5 + $q*25, $iWidth - 10, $iButtonHeight - 4)
                        GUICtrlSetState(Execute('$aSpoiler' & $j & '[' & $q & ']'), $GUI_SHOW)
                    Next
                EndIf
            Next
            For $y = $j + 1 To UBound($aButtons) - 1 ; все кнопки групп, находящиеся ниже - опускаем вниз к границе панели
                GUICtrlSetPos($aButtons[$y], $iLeft, $aPos[3] - $iBottom - (UBound($aButtons) - $y)*$iButtonHeight)
                GUICtrlSetResizing($aButtons[$y], $GUI_DOCKLEFT + $GUI_DOCKBOTTOM + $GUI_DOCKSIZE) ; прикрепляем к левому и нижнему краям, фиксируем размер
            Next
            ExitLoop
        EndIf
    Next
    For $l = 1 To 21 ; нажатие кнопок вложений
        If $msg = Eval('b' & $l) Then MsgBox(0, '', 'You a push the button # ' & GUICtrlRead(Eval('b' & $l)), 2)
    Next
WEnd

А так же функции библиотеки Scroll Bar
Код:
#AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
#include <GUIScrollBars.au3>
#include <ScrollBarConstants.au3>

Opt("MustDeclareVars", 1)

_Main()

Func _Main()
    Local $nFileMenu, $nExititem, $GUIMsg, $hGUI, $h_cGUI, $h_cGUI2
    Local $listview, $button

    $hGUI = GUICreate("ScrollBar Example", 400, 400, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_SIZEBOX))
    GUISetBkColor(0x88AABB)
    
    $nFileMenu = GUICtrlCreateMenu("File")
    $nExititem = GUICtrlCreateMenuItem("Exit", $nFileMenu)
    $listview = GUICtrlCreateListView("col1  |col2|col3  ", 10, 10, 200, 150);,$LVS_SORTDESCENDING)
    $button = GUICtrlCreateButton("Value?", 75, 170, 70, 20)
    GUICtrlSetResizing($button, $GUI_DOCKALL)
    For $x = 1 To 30
        GUICtrlCreateListViewItem("item" & $x & "|col2|col3", $listview)
    Next
    GUICtrlSetResizing($listview, $GUI_DOCKALL)
    
    $h_cGUI = GUICreate("Child GUI", 200, 200, 10, 200, $WS_CHILD, $WS_EX_CLIENTEDGE, $hGUI)
    GUICtrlCreateButton("a button", 10, 10, 90, 20)
    GUISetBkColor(0X006400)
    GUISetState()
    GUICtrlSetResizing($h_cGUI, $GUI_DOCKALL)

    GUISwitch($hGUI)

    $h_cGUI2 = GUICreate("Child GUI", 200, 200, 215, 10, $WS_CHILD, $WS_EX_CLIENTEDGE, $hGUI)
    GUICtrlCreateButton("a button", 10, 10, 90, 20)
    GUISetBkColor(0X006400)
    GUISetState()
    GUICtrlSetResizing($h_cGUI2, $GUI_DOCKALL)

    GUISwitch($hGUI)

    GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL")
    
    
    GUISetState()

    _GUIScrollBars_Init($hGUI)
    _GUIScrollBars_Init($h_cGUI)

    While 1
        $GUIMsg = GUIGetMsg()

        Switch $GUIMsg
            Case $GUI_EVENT_CLOSE, $nExititem
                ExitLoop
                Case $button
        EndSwitch
    WEnd

    Exit
EndFunc   ;==>_Main

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

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


    ; Get all the vertial scroll bar information
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    ; Save the position for comparison later on
    $yPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $yPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")

    Switch $nScrollCode
        Case $SB_TOP ; user clicked the HOME keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Min)

        Case $SB_BOTTOM ; user clicked the END keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Max)

        Case $SB_LINEUP ; user clicked the top arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)

        Case $SB_LINEDOWN ; user clicked the bottom arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)

        Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)

        Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)

        Case $SB_THUMBTRACK ; user dragged the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch
    
;~    // Set the position and then retrieve it.  Due to adjustments
;~    //   by Windows it may not be the same as the value set.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    ;// If the position has changed, scroll the window and update it
    $Pos = DllStructGetData($tSCROLLINFO, "nPos")

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

    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_VSCROLL
 
Верх