GDI+ Backbuffer - aber wie?!

  • Hallo,

    Ich schnuppere jetzt auch mal in GDI+ rein. (Scheint ja momentan in zu sein.)
    Ich habe jetzt mal dieses einfache Script gebaut:

    Spoiler anzeigen
    [autoit]


    #include <Misc.au3>
    #include <GUIConstantsEx.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>

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

    $GUI_Back_Color = 0xF0F0F0

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

    Global $x = 300, $y = 300
    Global $iSize = 15, $iPen = 2
    Global $iColor = 0xFFAA3366

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

    Opt("GUIOnEventMode", 1)

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

    $hDLL = DllOpen("user32.dll")
    $hGUI = GUICreate("", 600, 600)
    GUISetOnEvent(-3, "_Eventhandler")
    GUIRegisterMsg($WM_PAINT, "WM_PAINT")

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

    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) ; Graphic obj erstellen
    $hPen = _GDIPlus_PenCreate($iColor, $iPen) ; Pinsel erstellen
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000 + $GUI_Back_Color)
    ;~ $hBackbuffer = _GDIPlus_GraphicsGetDC($hGraphic) ; Backbuffer erstellen
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INTERNALPAINT) ; Fenster intern schonmal zeichnen

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

    GUISetState()

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

    WM_PAINT()

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

    $t = TimerInit()
    While 1
    If TimerDiff($t) > 10 Then
    Sleep(10)
    $t = TimerInit()
    EndIf
    _KeyHandler()
    WEnd

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

    Func WM_PAINT()
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_UPDATENOW)
    ;~ _GDIPlus_GraphicsFillRect($hBackbuffer, 0, 0, 600, 300, $hBrush)
    ;~ _GDIPlus_GraphicsDrawLine($hBackbuffer, $x - $iSize, $y, $x + $iSize, $y, $hPen) ; Fadenkreuz malen
    ;~ _GDIPlus_GraphicsDrawLine($hBackbuffer, $x, $y - $iSize, $x, $y + $iSize, $hPen)
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_VALIDATE)

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

    _WinAPI_RedrawWindow($hGUI)
    _GDIPlus_GraphicsDrawLine($hGraphic, $x - $iSize, $y, $x + $iSize, $y, $hPen) ; Fadenkreuz malen
    _GDIPlus_GraphicsDrawLine($hGraphic, $x, $y - $iSize, $x, $y + $iSize, $hPen)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func _Eventhandler()
    Switch @GUI_CtrlId
    Case -3
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    ;~ _WinAPI_ReleaseDC($hGUI,$hBackbuffer)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    EndFunc ;==>_Eventhandler

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

    Func _KeyHandler()

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

    If _IsPressed(25, $hDLL) Then ; links
    $x -= 1
    If $x < 0 Then $x = 0
    WM_PAINT()
    EndIf

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

    If _IsPressed(27, $hDLL) Then ; rechts
    $x += 1
    If $x > 599 Then $x = 599
    WM_PAINT()
    EndIf

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

    If _IsPressed(26, $hDLL) Then ; oben
    $y -= 1
    If $y < 0 Then $y = 0
    WM_PAINT()
    EndIf

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

    If _IsPressed(28, $hDLL) Then; unten
    $y += 1
    If $y > 599 Then $y = 599
    WM_PAINT()
    EndIf

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

    If _IsPressed("6B", $hDLL) Then ; Plus ( NumPad )
    $iSize += 1
    WM_PAINT()
    EndIf

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

    If _IsPressed("6D", $hDLL) Then ; Minus ( NumPad )
    $iSize -= 1
    If $iSize < 1 Then $iSize = 1
    WM_PAINT()
    EndIf

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

    If _IsPressed("6A", $hDLL) Then
    $iPen += 1
    _GDIPlus_PenDispose($hPen)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen)
    WM_PAINT()
    EndIf

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

    If _IsPressed("6F", $hDLL) Then
    $iPen -= 1
    If $iPen < 1 Then $iPen = 1
    _GDIPlus_PenDispose($hPen)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen)
    WM_PAINT()
    EndIf

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

    If _IsPressed("20", $hDLL) Then
    Local $iChosen = _ChooseColor(2)
    If @error Then Return
    $iColor = 0xFF000000 + $iChosen
    _GDIPlus_PenDispose($hPen)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen)
    WM_PAINT()
    EndIf
    EndFunc ;==>_KeyHandler

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


    Mit den Pfeiltasten kann man das Fadenkreuz bewegen, und mit + / - auf dem Numpad kann man die Größe des Kreuzes ändern,
    mit * und / kann man die Breite vom Pen verändern. Mit space kann man sich ne Farbe aussuchen.

    Folgendes Problem: Das Kreuz flackert. Ich weiß, dass ich hierfür Backbuffern muss (kenne das auch Blitz3D) ich weiß aber ehrlich gesagt nicht wie ich das anstellen soll. Ich hab mir nochmal den Thread vom letzen malangeschaut, aber ich komm auf keinen Grünen Zweig - ich habs sogar schon geschafft, dass das Script mit einem Hard Crash abstürzt :S

    Wäre toll, wenn mir jemand Erleuchtung verschaffen könnte.

  • [autoit]


    _GDIPlus_Startup()
    Global $graphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
    Global $bitmap = _GDIPlus_BitmapCreateFromGraphics($Width, $Height, $graphics)
    Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)

    [/autoit]


    Dann zeichnest du in den $backbuffer und malst am Ende das Bild $bitmap auf $graphics.

    PS: Ich kenne es auch aus Blitz3D und es ist fast genau so leicht, wenn man es erstmal kapiert hat

    Einmal editiert, zuletzt von TheShadowAE (10. März 2010 um 13:59)

  • Spoiler anzeigen
    [autoit]


    #include <Misc.au3>
    #include <GUIConstantsEx.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>

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

    $GUI_Back_Color = 0xF0F0F0

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

    Global $x = 300, $y = 300
    Global $iSize = 15, $iPen = 2
    Global $iColor = 0xFFAA3366

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

    Opt("GUIOnEventMode", 1)

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

    $hDLL = DllOpen("user32.dll")
    $hGUI = GUICreate("", 600, 600)
    GUISetOnEvent(-3, "_Eventhandler")
    GUIRegisterMsg($WM_PAINT, "WM_PAINT")

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

    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) ; Graphic obj erstellen
    $bitmap = _GDIPlus_BitmapCreateFromGraphics(600, 600, $hGraphic)
    $backbuffer = _GDIPlus_ImageGetGraphicsContext($bitmap)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen) ; Pinsel erstellen
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000 + $GUI_Back_Color)
    ;~ $hBackbuffer = _GDIPlus_GraphicsGetDC($hGraphic) ; Backbuffer erstellen
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INTERNALPAINT) ; Fenster intern schonmal zeichnen

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

    GUISetState()

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

    WM_PAINT()

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

    $t = TimerInit()
    While 1
    If TimerDiff($t) > 10 Then
    Sleep(10)
    $t = TimerInit()
    EndIf
    _KeyHandler()
    WEnd

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

    Func WM_PAINT()
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_UPDATENOW)
    ;~ _GDIPlus_GraphicsFillRect($hBackbuffer, 0, 0, 600, 300, $hBrush)
    ;~ _GDIPlus_GraphicsDrawLine($hBackbuffer, $x - $iSize, $y, $x + $iSize, $y, $hPen) ; Fadenkreuz malen
    ;~ _GDIPlus_GraphicsDrawLine($hBackbuffer, $x, $y - $iSize, $x, $y + $iSize, $hPen)
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_VALIDATE)

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

    ; _WinAPI_RedrawWindow($hGUI)
    _GDIPlus_GraphicsFillRect($backbuffer, 0, 0, 600, 600, $hbrush)
    _GDIPlus_GraphicsDrawLine($backbuffer , $x - $iSize, $y, $x + $iSize, $y, $hPen) ; Fadenkreuz malen
    _GDIPlus_GraphicsDrawLine($backbuffer , $x, $y - $iSize, $x, $y + $iSize, $hPen)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $bitmap, 0, 0, 600, 600)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func _Eventhandler()
    Switch @GUI_CtrlId
    Case -3
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    ;~ _WinAPI_ReleaseDC($hGUI,$hBackbuffer)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    EndFunc ;==>_Eventhandler

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

    Func _KeyHandler()

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

    If _IsPressed(25, $hDLL) Then ; links
    $x -= 1
    If $x < 0 Then $x = 0
    WM_PAINT()
    EndIf

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

    If _IsPressed(27, $hDLL) Then ; rechts
    $x += 1
    If $x > 599 Then $x = 599
    WM_PAINT()
    EndIf

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

    If _IsPressed(26, $hDLL) Then ; oben
    $y -= 1
    If $y < 0 Then $y = 0
    WM_PAINT()
    EndIf

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

    If _IsPressed(28, $hDLL) Then; unten
    $y += 1
    If $y > 599 Then $y = 599
    WM_PAINT()
    EndIf

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

    If _IsPressed("6B", $hDLL) Then ; Plus ( NumPad )
    $iSize += 1
    WM_PAINT()
    EndIf

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

    If _IsPressed("6D", $hDLL) Then ; Minus ( NumPad )
    $iSize -= 1
    If $iSize < 1 Then $iSize = 1
    WM_PAINT()
    EndIf

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

    If _IsPressed("6A", $hDLL) Then
    $iPen += 1
    _GDIPlus_PenDispose($hPen)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen)
    WM_PAINT()
    EndIf

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

    If _IsPressed("6F", $hDLL) Then
    $iPen -= 1
    If $iPen < 1 Then $iPen = 1
    _GDIPlus_PenDispose($hPen)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen)
    WM_PAINT()
    EndIf

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

    If _IsPressed("20", $hDLL) Then
    Local $iChosen = _ChooseColor(2)
    If @error Then Return
    $iColor = 0xFF000000 + $iChosen
    _GDIPlus_PenDispose($hPen)
    $hPen = _GDIPlus_PenCreate($iColor, $iPen)
    WM_PAINT()
    EndIf
    EndFunc ;==>_KeyHandler

    [/autoit]


    So gehts mit Backbuffer.

    edit \ Beim verlassen aber den Buffer noch freigeben (check das Skript nicht so ganz :D).

    [autoit]

    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_BitmapDispose($bitmap)

    [/autoit]


    Bei der Exit Funktion einfügen.

  • Oder so:

    Spoiler anzeigen
    [autoit]


    #include <Misc.au3>
    #include <GUIConstantsEx.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>

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

    $GUI_Back_Color = 0xF0F0F0

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

    Global $x = 300, $y = 300
    Global $iSize = 15, $iPen = 2
    Global $iColor = 0xFFAA3366

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

    Opt("GUIOnEventMode", 1)
    $Width = 600
    $Height = 600
    $hDLL = DllOpen("user32.dll")
    $hGUI = GUICreate("", $Width, $Height)
    GUISetOnEvent(-3, "_Eventhandler")
    GUIRegisterMsg($WM_PAINT, "WM_PAINT")

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

    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) ; Graphic obj erstellen
    $hPen = _GDIPlus_PenCreate($iColor, $iPen) ; Pinsel erstellen
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000 + $GUI_Back_Color)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($Width, $Height, $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    ;~ _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INTERNALPAINT) ; Fenster intern schonmal zeichnen

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

    GUISetState()

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

    WM_PAINT()

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

    $t = TimerInit()
    While 1
    If TimerDiff($t) > 10 Then
    Sleep(10)
    $t = TimerInit()
    EndIf
    _KeyHandler()
    WEnd

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

    Func WM_PAINT()
    ;~ _WinAPI_RedrawWindow($hGUI)
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFF000000 + $GUI_Back_Color)
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $x - $iSize, $y, $x + $iSize, $y, $hPen) ; Fadenkreuz malen
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $x, $y - $iSize, $x, $y + $iSize, $hPen)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $width, $height)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func _Eventhandler()
    Switch @GUI_CtrlId
    Case -3
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    ;~ _WinAPI_ReleaseDC($hGUI,$hBackbuffer)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    EndFunc ;==>_Eventhandler

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

    Func _KeyHandler()

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

    If _IsPressed(25, $hDLL) Then ; links
    $x -= 2
    If $x < 0 Then $x = 0
    WM_PAINT()
    EndIf

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

    If _IsPressed(27, $hDLL) Then ; rechts
    $x += 2
    If $x > 599 Then $x = 599
    WM_PAINT()
    EndIf

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

    If _IsPressed(26, $hDLL) Then ; oben
    $y -= 2
    If $y < 0 Then $y = 0
    WM_PAINT()
    EndIf

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

    If _IsPressed(28, $hDLL) Then; unten
    $y += 2
    If $y > 599 Then $y = 599
    WM_PAINT()
    EndIf

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

    If _IsPressed("6B", $hDLL) Then ; Plus ( NumPad )
    $iSize += 1
    WM_PAINT()
    EndIf

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

    If _IsPressed("6D", $hDLL) Then ; Minus ( NumPad )
    $iSize -= 1
    If $iSize < 1 Then $iSize = 1
    WM_PAINT()
    EndIf

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

    If _IsPressed("6A", $hDLL) Then ;*
    $iPen += 10
    ConsoleWrite(Hex($iPen, 8) & @CRLF)
    _GDIPlus_PenSetWidth($hPen, $iPen)
    WM_PAINT()
    EndIf

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

    If _IsPressed("6F", $hDLL) Then ;/
    $iPen -= 10
    If $iPen < 1 Then $iPen = 1
    ConsoleWrite(Hex($iPen, 8) & @CRLF)
    _GDIPlus_PenSetWidth($hPen, $iPen)
    WM_PAINT()
    EndIf

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

    If _IsPressed("20", $hDLL) Then
    Local $iChosen = _ChooseColor(2)
    If @error Then Return
    $iColor = 0xFF000000 + $iChosen
    _GDIPlus_PenSetColor($hPen, $iColor)
    WM_PAINT()
    EndIf
    EndFunc ;==>_KeyHandler

    [/autoit]


    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯