Probleme mit Scrollbalken: Steuerelemente werden verschoben und GDI+-Grafik verschwindet

  • Hallo liebe AuoIt-Community!

    Ich habe zwei Fragen zur Verwendung von Scrollbalken in GUIs.

    1. Wie lässt sich verhindern, dass Steuerelemente (z. B. Buttons) beim Scrollen verschoben werden?

    2. Eine mit GDI+ gezeichnete Grafik (Linie), die länger ist als das GUI wird beim Scrollen kürzer. Wie lässt sich dieses verhindern?

    Vielen Dank für Eure Hilfe!

    Spoiler anzeigen
    [autoit]

    #include-once
    #include <GDIPlus.au3>
    #include <GUIConstants.au3>
    #include <GUIScrollbars.au3>
    #include <ScrollBarConstants.au3>
    #include <WindowsConstants.au3>

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

    Opt("GUIOnEventMode", 1)

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

    Global $x1 = 0, $x2 = 600, $xScroll

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

    HotKeySet("{LEFT}", "_Scrollen")
    HotKeySet("{RIGHT}", "_Scrollen")

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

    $Fenster = GUICreate("Fenster zu Testzwecken", 500, 500, Default, Default, BitOR(Default, $WS_HSCROLL))
    $Button1 = GUICtrlCreateButton("Zeichnen", 0, 0, 75, 25)
    GUICtrlSetOnEvent(-1, "_Zeichnen")
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Beenden")
    GUISetState()

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

    _GUIScrollBars_Init($Fenster)
    _GUIScrollBars_ShowScrollBar($Fenster, $SB_VERT, False)
    _GUIScrollBars_SetScrollRange($Fenster, $SB_HORZ, 0, 100)
    _GUIScrollBars_SetScrollInfoPage($Fenster, $SB_HORZ, 5)
    GUIRegisterMsg($WM_HSCROLL, "_SystemScrollen")
    GUIRegisterMsg($WM_VSCROLL, "_SystemScrollen")

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

    _GDIPlus_Startup()

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

    $Grafik = _GDIPlus_GraphicsCreateFromHWND($Fenster)
    $Stift = _GDIPlus_PenCreate(0xFF000000, 5)

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

    _Zeichnen ()

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

    Do
    Until GUIGetMsg() = -3

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

    Func _Zeichnen ()
    _GDIPlus_GraphicsDrawLine($Grafik, $x1, 250, $x2, 250, $Stift)
    EndFunc

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

    Func _Scrollen ()
    $xScroll = 0
    Switch @HotKeyPressed
    Case "{LEFT}"
    If $x1+$xScroll > 0 Then $xScroll -= 10
    Case "{RIGHT}"
    $xScroll +=10
    EndSwitch
    _GUIScrollBars_ScrollWindow($Fenster, $xScroll, 0)
    $x1 += $xScroll
    $x2 += $xScroll
    EndFunc

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

    Func _SystemScrollen ($hWndGUI, $MsgID, $WParam, $LParam)
    _GUIScrollBars_SetScrollInfoPos($Fenster, $SB_HORZ, _GUIScrollBars_GetScrollInfoTrackPos($Fenster, $SB_HORZ))
    $x1 += $WParam
    $x2 += $WParam
    EndFunc

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

    Func _Beenden ()
    _GDIPlus_PenDispose($Stift)
    _GDIPlus_GraphicsDispose($Grafik)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]
  • Zu deinem ersten Problem habe ich leider keine saubere Lösung. Eventuell spuckt die Forensuche ja etwas aus, oder ein anderer weiß mehr dazu.
    Dein zweites Problem habe ich so gelöst (hoffentlich):

    Spoiler anzeigen
    [autoit]

    #include-once
    #include <GDIPlus.au3>
    #include <GUIConstants.au3>
    #include <GUIScrollbars.au3>
    #include <ScrollBarConstants.au3>
    #include <WindowsConstants.au3>

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

    Opt("GUIOnEventMode", 1)

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

    Global $x1 = 0, $x2 = 600, $xScroll

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

    HotKeySet("{LEFT}", "_Scrollen")
    HotKeySet("{RIGHT}", "_Scrollen")

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

    $Fenster = GUICreate("Fenster zu Testzwecken", 500, 500, Default, Default, BitOR(Default, $WS_HSCROLL))
    $Button1 = GUICtrlCreateButton("Zeichnen", 0, 0, 75, 25)
    GUICtrlSetOnEvent(-1, "_Zeichnen")
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Beenden")
    GUISetOnEvent($GUI_EVENT_RESTORE, "_Zeichnen") ;Zeichnet die Linie bei Wiederherstellung des Fensters (nach Minimierung) neu.
    GUISetState()

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

    _GUIScrollBars_Init($Fenster)
    _GUIScrollBars_ShowScrollBar($Fenster, $SB_VERT, False)
    _GUIScrollBars_SetScrollRange($Fenster, $SB_HORZ, 0, 100)
    _GUIScrollBars_SetScrollInfoPage($Fenster, $SB_HORZ, 5)
    GUIRegisterMsg($WM_HSCROLL, "_SystemScrollen")
    GUIRegisterMsg($WM_VSCROLL, "_SystemScrollen")
    GUIRegisterMsg($WM_PAINT, "_Zeichnen") ;Zeichnet die Linie nach einer Überdeckung durch ein anderes Fenster oder einem Verschieben des Fensters aus dem Arbeitsbereich etc. neu.

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

    _GDIPlus_Startup()

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

    $Grafik = _GDIPlus_GraphicsCreateFromHWND($Fenster)
    $Stift = _GDIPlus_PenCreate(0xFF000000, 5)

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

    _Zeichnen ()

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

    Do
    Until GUIGetMsg() = -3

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

    Func _Zeichnen ()
    _GDIPlus_GraphicsDrawLine($Grafik, $x1, 250, $x2, 250, $Stift)
    EndFunc

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

    Func _Scrollen ()
    $xScroll = 0
    Switch @HotKeyPressed
    Case "{LEFT}"
    If $x1+$xScroll > 0 Then $xScroll -= 10
    Case "{RIGHT}"
    $xScroll +=10
    EndSwitch
    _GUIScrollBars_ScrollWindow($Fenster, $xScroll, 0)
    $x1 += $xScroll
    $x2 += $xScroll
    EndFunc

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

    Func _SystemScrollen ($hWndGUI, $MsgID, $WParam, $LParam)
    _GUIScrollBars_SetScrollInfoPos($Fenster, $SB_HORZ, _GUIScrollBars_GetScrollInfoTrackPos($Fenster, $SB_HORZ))
    $x1 += $WParam
    $x2 += $WParam
    _Zeichnen()
    EndFunc

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

    Func _Beenden ()
    _GDIPlus_PenDispose($Stift)
    _GDIPlus_GraphicsDispose($Grafik)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]


    Allerdings ist diese Lösung auch nicht so wirklich optimal (finde ich zumindest). An deiner Stelle, würde ich die Controls und GDI+ klar trennen, also z.B. so. Den Scrollbalken könnte man auch mit GDI+ zeichnen, oder ganz weglassen und durch eine kleine Funktion ersetzen, die es ermöglicht die Grafik per Maus zu "ziehen".

  • Hallo name22,
    vielen Dank für Deine Hilfe!
    Die Lösung durch erneutes Zeichnen war mir klar.
    Das Problem ist, dass ich in meinem eigentlichen Programm keine Linie, sondern einen Graphen zeichnen lasse, der nicht periodisch ist, d. h. ich müsste die Werte sozusagen rückwärts, dem Scrollen entsprechend, wieder zeichnen.
    Ich hoffe, ich konnte mein Problem klar genug schildern.

    Edit: Die Trennung von Steuerlementen und Zeichnung halte ich für sinnvoll und auch das Ziehen der Grafik per Maus wäre für mich eine akzeptable Alternative.

  • Zitat

    Das Problem ist, dass ich in meinem eigentlichen Programm keine Linie, sondern einen Graphen zeichnen lasse, der nicht periodisch ist, d. h. ich müsste die Werte sozusagen rückwärts, dem Scrollen entsprechend, wieder zeichnen.


    Ach so... Dann wäre es vermutlich wirklich einfacher, das komplett über GDI+ zu regeln (was den Graphen betrifft). Der Scrollbalken wäre ja nur für die restlichen Controls entscheidend, und die sollen in deinem Fall ja sowieso am Platz bleiben.
    Am sinnvollsten für eine Grafik, die eine 2-dimensionale Ausdehung hat, halte ich das ziehen der Grafik per Cursor. Dann müsste die Mausposition beim betätigen der linken Maustaste ständig abgefragt werden, und alle Koordinaten der GDI+ Elemente entsprechend verschoben werden. Dann wird alles mit den angepassten Positionen neugezeichnet.

  • Ja. Allerdings würde ich die Punkte des Graphen einmal berechnen, in einem Array abspeichern und bei jeder Verschiebung vor dem zeichnen einfach immer einen bestimmten Wert addieren/subtrahieren. Also so dass der Wert im Array gleich bleibt. Außerdem würde ich noch einen Doppelbuffer einbauen, um das flackern bei Zeichenvorgängen zu minimieren und damit man nicht bei jedem Zeichenvorgang alles neuberechnen/-zeichnen muss sondern nur eine Bitmap auf die Grafik malt. Das ganze kannst du dir auch in Ubuntus GDI+ Tutorial anschauen.