Scrollbar GUI

  • Ich habe nur Probleme mit den Scrollbars in meinen GUIs ...

    Was ich möchte:
    Das ich die Größe der Scrollbar-GUI ändern kann. Nicht die Scrollbar selbst, auch nicht die Child-GUI, sondern der eigentliche Bereich in der Child-GUI!
    Wenn ich den Inhalt in der Child-Gui ändere, soll sich der scrollbare Bereich dazu auch anpassen!

    Hier mal zwei Systeme, wie ich die Scrollbar anwende:

    Mein Zusammengeschusterttes Skript
    [autoit]

    #include <ButtonConstants.au3>
    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GuiScrollBars.au3>
    #include <ScrollBarConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $gui_db = GUICreate("Test", 500, 300, -1, -1)
    $knopf = GUICtrlCreateButton("Neuordnen", 10, 260, 100, 30)

    [/autoit] [autoit][/autoit] [autoit]

    $gui_db_scroll = GUICreate("", 500, 200, 0, 50, BitOR($WS_POPUP, $WS_GROUP, $WS_VSCROLL, $WS_CLIPSIBLINGS), $WS_EX_MDICHILD, $gui_db)
    GUISetBkColor(0xc0d8f1)

    [/autoit] [autoit][/autoit] [autoit]

    local $Label[20]
    for $n=0 to 19
    $Label[$n] = GUICtrlCreateLabel("Label" & $n+1, 10, $n*30+10)
    next

    [/autoit] [autoit][/autoit] [autoit]

    crys_scroll()
    _GUIScrollBars_Init($gui_db_scroll, -1, 40)
    _GUIScrollBars_ShowScrollBar($gui_db_scroll, $SB_HORZ, False)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW, $gui_db)
    GUISetState(@SW_SHOW, $gui_db_scroll)

    [/autoit] [autoit][/autoit] [autoit]

    while 1
    Switch GUIGetMsg()
    case $GUI_EVENT_CLOSE
    exitloop
    case $knopf
    for $x=5 to 19
    GUICtrlDelete($Label[$x])
    next
    crys_scroll()
    _GUIScrollBars_Init($gui_db_scroll, -1, 10)
    _GUIScrollBars_ShowScrollBar($gui_db_scroll, $SB_HORZ, False)
    EndSwitch
    wend

    [/autoit] [autoit][/autoit] [autoit]

    ; ### Scrollen mit Mausrad ermöglichen ###
    Func crys_scroll()
    ; kein scollen unter 64bit
    if @AutoItX64 then
    MsgBox(48, "Achtung", "Kein Maus-scollen in der 64bit Version dieses Programmes möglich!", 2)
    endif
    ;MsgBox(0, "", "Scrollen gestartet!", 1)

    GUIRegisterMsg($WM_SIZE, "crys_scroll_size")
    GUIRegisterMsg($WM_VSCROLL, "crys_scroll_vscroll")
    if @AutoItX64 = 0 then GUIRegisterMsg($WM_MOUSEWHEEL, "crys_scroll_mouse")
    EndFunc
    Func crys_scroll_mouse($hWnd, $Msg, $wParam, $lParam)
    #forceref $Msg, $wParam
    If $wParam == "0x00780000" then
    for $i = 0 To 4 Step 1
    crys_scroll_vscroll($hWnd, 0x0, 0x00000000, 0) ;1 mal kurz nach oben Scrollen - selber Effekt wie auf den Pfeil klicken
    Next

    ElseIf $wParam == "0xFF880000" then
    for $i = 0 To 4 Step 1
    crys_scroll_vscroll($hWnd, 0x0, 0x00000001, 0) ;1 mal kurz nach unten Scrollen - selber Effekt wie auf den Pfeil klicken
    Next
    EndIf
    EndFunc
    Func crys_scroll_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

    [/autoit] [autoit][/autoit] [autoit]

    Local $tSCROLLINFO = DllStructCreate($tagSCROLLINFO)

    [/autoit] [autoit][/autoit] [autoit]

    ; 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

    [/autoit] [autoit][/autoit] [autoit]

    ; Set the vertical scrolling range and page size
    DllStructSetData($tSCROLLINFO, "fMask", BitOR($SIF_RANGE, $SIF_PAGE, $SIF_POS))
    DllStructSetData($tSCROLLINFO, "nMin", 0)
    DllStructSetData($tSCROLLINFO, "nMax", $ivMax)
    DllStructSetData($tSCROLLINFO, "nPage", $yClient / $yChar)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)

    [/autoit] [autoit][/autoit] [autoit]

    ; Set the horizontal scrolling range and page size
    DllStructSetData($tSCROLLINFO, "fMask", BitOR($SIF_RANGE, $SIF_PAGE, $SIF_POS))
    DllStructSetData($tSCROLLINFO, "nMin", 0)
    DllStructSetData($tSCROLLINFO, "nMax", 2 + $xClientMax / $xChar)
    DllStructSetData($tSCROLLINFO, "nPage", $xClient / $xChar)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)

    [/autoit] [autoit][/autoit] [autoit]

    Return $GUI_RUNDEFMSG
    EndFunc
    Func crys_scroll_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

    [/autoit] [autoit][/autoit] [autoit]

    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

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; 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")

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    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")

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit]

    Ich verstehe nicht, was ich bei _GUIScrollBars_Init() für die Seitenhöhe eingeben soll ... ich habe "40" eingetippt, dass sind aber weder Pixel noch Zoll ...
    Wenn man auf den Button "Neuordnen" klickt, passiert nicht was wahre mit der Scrollbar, die verändert sich, wird aber nicht kleiner!


    Nach Großvater

    Link zum Thread

    [autoit]

    #include <ButtonConstants.au3>
    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include "GuiScroll.au3"

    [/autoit] [autoit][/autoit] [autoit]

    $gui_db = GUICreate("Test", 500, 300, -1, -1)
    $knopf = GUICtrlCreateButton("Neuordnen", 10, 260, 100, 30)

    [/autoit] [autoit][/autoit] [autoit]

    $gui_db_scroll = GUICreate("", 500, 200, 0, 50, BitOR($WS_POPUP, $WS_GROUP, $WS_VSCROLL, $WS_CLIPSIBLINGS), $WS_EX_MDICHILD, $gui_db)
    GUISetBkColor(0xc0d8f1)

    [/autoit] [autoit][/autoit] [autoit]

    local $Label[20]
    for $n=0 to 19
    $Label[$n] = GUICtrlCreateLabel("Label" & $n+1, 10, $n*30+10)
    next

    [/autoit] [autoit][/autoit] [autoit]

    _GUIScroll_Init($gui_db_scroll, 1, 1, 20)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW, $gui_db)
    GUISetState(@SW_SHOW, $gui_db_scroll)

    [/autoit] [autoit][/autoit] [autoit]

    while 1
    Switch GUIGetMsg()
    case $GUI_EVENT_CLOSE
    exitloop
    case $knopf
    for $x=5 to 19
    GUICtrlDelete($Label[$x])
    next
    _GUIScroll_Init($gui_db_scroll, 1, 1, 20)
    EndSwitch
    wend

    [/autoit]

    Wenn man hier auf den Button "Neuordnen" klickt, passiert überhaupt nichts!
    Und es gibt den Bug, dass man auch die Haupt-GUI scrollen kann ... wieso auch immer!


    Btw.: Wenn ich gerade dabei bin...

    ... kann man es verhindern, dass wenn man etwas in der Child-GUI anklickt, die Haupt-GUI den Fokus verliert?

    Und das die Haupt-Gui von der Startleiste so einen Effekt macht, wenn man das Programm startet ... es wird von der Startleiste her größer .. wie jedes Programm, das man ab Vista von der Startleiste holt. Weil die Child-GUI poppt immer ohne Effekt vorher an der stelle hin, bevor die Haupt-GUI da angekommen ist!

  • Die Grundlagen kenn ich ja, meine Scrollbar(s) funktionieren ja!
    Ich kann zwar recht gut englisch, das meiste verstehe ich, kenne aber nur wenige IT-Fachbegriffe auf deutsch ... noch weniger auf englisch, habe da ein paar Probleme.
    Auch finde ich da kein Beispiel ...

    Ich denke, dass es am $WS_VSCROLL Parameter von Windows liegt, denn tut der nicht aktualisieren ...
    Wenn ich "crys_scroll()" bzw "_GUIScroll_Init()" ein weiteres mal aufrufe, sollte AutoIt ja $WS_VSCROLL neu bestimmen, macht der aber irgendwie nicht.

  • Ich meinte das Beispiel aus der AutoIt-Hilfe: _GUIScrollBars_Init

    Das ist schon ein Triviales Beispiel (ironie) und ich weiß auch nicht, ob das so aussehen soll:
    [Blockierte Grafik: http://saved.im/mtg2mjm5d2tq_vs/autoit_scrollbar_beispiel.png]
    Zumindest sieht es so bei mir aus ... aber dort is ja alles wie in meinem Beispiel ...
    ... und nichts mit neu berechnen der Scrollbar-Größe!

    Beispiele in der MSDN findest Du hier: Using Scroll Bars

    Ich finde da immer noch keine AutoIt Beispiele ...

    EDIT: Warum soll Dein Skript nicht unter 64bit laufen ?

    Wer hat das behauptet?
    Das Maus-Scrollen funktioniert in meiner Version nicht, wenn das Skript als x64 kompiliert wurde.

  • Ich denke, dass es am $WS_VSCROLL Parameter von Windows liegt, denn tut der nicht aktualisieren ...
    Wenn ich "crys_scroll()" bzw "_GUIScroll_Init()" ein weiteres mal aufrufe, sollte AutoIt ja $WS_VSCROLL neu bestimmen, macht der aber irgendwie nicht.


    Ich habe mir die Funktion _GUIScroll_Init einmal angesehen. Wenn Du Die Funktion ein zweites mal aufrufst, dann wird das globale Array $aSB_WindowInfo erweitert. D.h. Dein erster Eintrag für das jeweilige Fenster bleibt bestehen und da wird der Hund begraben liegen, denke ich.


  • Du musst nach dem Neuordnen nMax neu berechnen und dann SetScrollInfo aufrufen. So ähnlich, wie Du es in der WM_Size machst.
    SetScrollRange könntest Du auch dafür benutzen.


  • Danke Greenhorn!
    Jetzt klappt's ...

    Ich habe es jetzt noch einmal mit _GUIScrollBars_SetScrollRange() probiert und habe etwas festgestellt: Der "Zahlenwert" darf nicht kleiner sein, als die Höhe der Child-GUI!
    Wenn man einen kleineren Wert einsetzt, passiert gar nichts.
    Mit "Zahlenwert" meine ich die Zahlen, die bei $nMinPos und $nMaxPos in _GUIScrollBars_SetScrollRange() (und andere _GUIScrollBars_Set[...]() Funktionen) eingesetzt wird!

    Durch ausprobieren habe ich herausgefunden, dass dieser "Zahlenwert" ungefähr ein 16tel der Pixel entspricht.
    In einen anderen Skript von mir ist die Child-GUI 432px hoch und ab einen "Zahlenwert" von 27 verändert sich nichts mehr mit _GUIScrollBars_SetScrollRange()! 437 / 27 => 16!

    Was ist das für ein "Zahlenwert", denn man in die _GUIScrollBars_Set[...]()-Funktionen einsetzt?