GDI+ Problem: Grafik erst erstellen, dann in Hauptgrafik einfügen. (Viele kleine PNG-Bilder zu Grp zusammenfassen, dann einfügen)

  • Guten Tag,

    Ich habe folgendes Problem:
    meine Popup-GUI besteht aus vielen PNG-Dateien. Wenn ich jetzt ein $WM_PAINT-Ereignis auslöse, dann werden sämtliche png's einzeln neu gezeichnet. Und das dauert lange! (also ein paar ms zu viel für mich)

    Dabei ist es gar nicht nötig alles neu übereinander zu legen.
    Ich möchte einzelne Bild(PNG)-Gruppen, schon vorher übereinanderlegen lassen, und dann bei Bedarf ($WM_PAINT) nur das komplette Gruppenbild einfügen.
    Geht das?

    Hier mal ein ganz kleines bisschen Code, ich hoffe das hilft... (Skript nicht ganz lauffähig, aber ich denke was ich möchte wird klar)

    Spoiler anzeigen
    [autoit]

    #include-once
    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>

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

    _GDIPlus_Startup()
    ; Set accelerators
    Global $SC_Width = 600
    Global $SC_Height = 526
    Global $SC_Titlebar_Height = 26
    Global $hWnd_SC = GUICreate('GUI', $SC_Width, $SC_Height, -1, -1,$WS_POPUP); $WS_CLIPCHILDREN;
    GUISetOnEvent($GUI_EVENT_CLOSE, "_exitMain")

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

    ;~ Global $hWnd_Chips = GUICreate("", 169, 68, 0, 0, $WS_POPUP, $WS_EX_LAYERED + $WS_EX_MDICHILD, $hWnd_SC)
    ;~ GUISetState(@SW_SHOW)

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

    ;~ WinWait('GUI')
    Global $Lbl_Title = GUICtrlCreateLabel('', 0, 0, $SC_Width, $SC_Titlebar_Height, -1, $GUI_WS_EX_PARENTDRAG )
    Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd_SC)

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

    ; these Controls are invisible, but have correct position for user interaction
    Global $SC_Btn_Dim = 16

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

    Global $XClose = GUICtrlCreateLabel('',$SC_Width- $SC_Btn_Dim, 0, $SC_Btn_Dim, $SC_Btn_Dim)
    GUICtrlSetOnEvent($XClose, "_exitMain")
    GUICtrlSetState ( $XClose, $GUI_ONTOP )

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

    ;these Controls have no dimension, only for functions fired by Hotkeys;
    Global $Lbl_Redraw_GUI = GUICtrlCreateLabel('',0,0,0,0)
    GUICtrlSetOnEvent($Lbl_Redraw_GUI, "_Redraw_GUI")

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

    Dim $Arr_AccelKeys[2][2]=[ _
    ['{SPACE}', $Lbl_Redraw_GUI], _
    ["!q", $XClose] _
    ]
    GUISetAccelerators($Arr_AccelKeys,$hWnd_SC)

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

    GUISetState()
    GUIRegisterMsg($WM_PAINT, "_Redraw_GUI")

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

    While True
    Sleep(1000)
    WEnd

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

    Func _Redraw_GUI()
    _WinAPI_RedrawWindow ($hWnd_SC, 0, 0, $RDW_UPDATENOW)
    _GDIPlus_GraphicsDrawImageRect ($hGraphic, $hImg_Pic, 3, 26, 600, 500) ; Bild
    _GDIPlus_GraphicsDrawImage ($hGraphic, $hImg_MinBG, 3, 429) ; IconHintergrund

    ;Diese Bilder hier möchte ich in eine Gruppe fassen, damit ich nur einen Befehl habe: _GDIPlus_GraphicsDrawImage ( $hGraphic, hImg_Icon, 10, 440)
    local $SC_Icon_Dim=10
    _GDIPlus_GraphicsDrawImageRectRect ($hGraphic, $hImg_Icon1, 0, 0, $SC_Icon_Dim, $SC_Icon_Dim, 10, 0*($SC_Icon_Dim+10)+440 , $SC_Icon_Dim, $SC_Icon_Dim) ; FooterIcon
    _GDIPlus_GraphicsDrawImageRectRect ($hGraphic, $hImg_Icon2, 0, 0, $SC_Icon_Dim, $SC_Icon_Dim, 10, 1*($SC_Icon_Dim+10)+440 , $SC_Icon_Dim, $SC_Icon_Dim) ; FooterIcon
    _GDIPlus_GraphicsDrawImageRectRect ($hGraphic, $hImg_Icon3, 0, 0, $SC_Icon_Dim, $SC_Icon_Dim, 10, 2*($SC_Icon_Dim+10)+440 , $SC_Icon_Dim, $SC_Icon_Dim) ; FooterIcon
    _GDIPlus_GraphicsDrawImageRectRect ($hGraphic, $hImg_Icon4, 0, 0, $SC_Icon_Dim, $SC_Icon_Dim, 10, 3*($SC_Icon_Dim+10)+440 , $SC_Icon_Dim, $SC_Icon_Dim) ; FooterIcon

    ; Hier folgen Viele weitere Bilder


    Return $GUI_RUNDEFMSG
    EndFunc


    Func _exitMain()
    ;~ _CollectGarbage()
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==> _exitMain

    [/autoit]

    Ich bedanke mich
    JStaxton

    Einmal editiert, zuletzt von JStaxton (30. November 2009 um 19:09)

  • Du kannst eine Bitmap im Speicher erzeigen und auf diese Zeichnen. Dann die Bitmap auf die GUI ;)

    [autoit]

    $hGraphicsGUI = _GDIPlus_GraphicsCreateFromHWnd($hWnd)
    $hBmpBackBuffer = _GDIPlus_BitmapCreateFromGraphics($Width, $height, $hGraphicsGUI)
    $hGraphicsBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBackBuffer)

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

    ; Vorzeichnen:
    _GDIPlus_GraphicsDrawRect($hGraphicsBackBuffer, 10, 10, 100, 100)

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

    ; Auf GUI:
    _GDIPlus_GraphicsDrawImage($hGraphicsGUI, 0, 0)

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

    ; Aufräumen
    _GDIPlus_GraphicsDispose($hGraphicsGUI)
    _GDIPlus_GraphicsDispose($hGraphicsBackBuffer)
    _GDIPlus_BitmapDispose($hBmpBackBuffer)

    [/autoit]
  • sobald ich Bitmap benutze, verliere ich dann nicht die Transparenz?

    Die übereinandergelegten Bilder sind immer noch teilweise transpartent und sollen den hintergrund durcherkennen lassen...

    Ich werd das mal ausprobieren.
    Vielen Dank für deine Antwort Progandy

    ps.: ich hab noch eine Frage: wenn ich ein Array voller GDIImageLoadFromFile erstelle, wie nutze ich dann den Befehl dispose?

  • sobald ich Bitmap benutze, verliere ich dann nicht die Transparenz?


    Ich glaube, nicht unbedingt.

    ps.: ich hab noch eine Frage: wenn ich ein Array voller GDIImageLoadFromFile erstelle, wie nutze ich dann den Befehl dispose?

    Wie immer mit einer Schleife ;)

    [autoit]

    For $i = 0 To Ubound($Bilder)-1
    _GDIPlus_ImageDispose($Bilder[$i])
    Next

    [/autoit]
  • hallo progandy und liebe community,

    ich habe versucht deinen Ansatz umzusetzen, bin aber gescheitert (fürs erste). Kannst du mir noch mal helfen?
    So sieht mein derzeitiger Testcode aus:

    Spoiler anzeigen
    [autoit]

    #include-once
    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    ;~ #include <MouseSetOnEvent_UDF.au3>

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

    Opt("GUIOnEventMode", 1) ; Wechsle in den OnEvent Modus
    Opt('PixelCoordMode' ,0 ) ; 0 = relative coords to the defined window

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

    _GDIPlus_Startup()
    Global $hWnd_SC = GUICreate('GUI', 500, 500, -1, -1); $WS_CLIPCHILDREN;
    GUISetOnEvent($GUI_EVENT_CLOSE, "_exitMain")

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

    $hGraphicsGUI = _GDIPlus_GraphicsCreateFromHWnd($hWnd_SC)
    $hBmpBackBuffer = _GDIPlus_BitmapCreateFromGraphics(500, 500, $hGraphicsGUI)
    $hGraphicsBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBackBuffer)

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

    ; Vorzeichnen:
    _GDIPlus_GraphicsDrawRect($hGraphicsBackBuffer, 10, 10, 100, 100)

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

    ; Auf GUI:
    _GDIPlus_GraphicsDrawImage($hGraphicsGUI, $hGraphicsBackBuffer, 0, 0)
    GUISetState()
    ;~ SetGui()
    While True
    Sleep(1000)
    WEnd

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

    Func _exitMain()
    ;~ _CollectGarbage()
    ; Aufräumen
    _GDIPlus_GraphicsDispose($hGraphicsGUI)
    _GDIPlus_GraphicsDispose($hGraphicsBackBuffer)
    _GDIPlus_BitmapDispose($hBmpBackBuffer)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==> _exitMain

    [/autoit]

    Ich sehe das Rechteck nicht, das gezeichnet werden sollte...


    Gruß
    JStaxton

  • GUISetState() muss vor der Zeichnung erfolgen und
    _GDIPlus_GraphicsDrawImage($hGraphicsGUI, $hGraphicsBackBuffer, 0, 0) ist falsch hier!

    Spoiler anzeigen
    [autoit]


    #include-once
    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    ;~ #include <MouseSetOnEvent_UDF.au3>

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

    Opt("GUIOnEventMode", 1) ; Wechsle in den OnEvent Modus
    Opt('PixelCoordMode' ,0 ) ; 0 = relative coords to the defined window

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

    _GDIPlus_Startup()
    Global $hWnd_SC = GUICreate('GUI', 500, 500, -1, -1); $WS_CLIPCHILDREN;
    GUISetState()
    GUISetOnEvent($GUI_EVENT_CLOSE, "_exitMain")

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

    $hGraphicsGUI = _GDIPlus_GraphicsCreateFromHWnd($hWnd_SC)
    $hBmpBackBuffer = _GDIPlus_BitmapCreateFromGraphics(500, 500, $hGraphicsGUI)
    $hGraphicsBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBackBuffer)

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

    ; Vorzeichnen:
    _GDIPlus_GraphicsDrawRect($hGraphicsBackBuffer, 10, 10, 100, 100)

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

    ; Auf GUI:
    _GDIPlus_GraphicsDrawImageRect($hGraphicsGUI, $hBmpBackBuffer, 0, 0, 500, 500)

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

    ;~ SetGui()
    While True
    Sleep(1000)
    WEnd

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

    Func _exitMain()
    ;~ _CollectGarbage()
    ; Aufräumen
    _GDIPlus_GraphicsDispose($hGraphicsGUI)
    _GDIPlus_GraphicsDispose($hGraphicsBackBuffer)
    _GDIPlus_BitmapDispose($hBmpBackBuffer)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==> _exitMain

    [/autoit]

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Hallo Leute,

    Ich bedanke mich für eure Hilfe! Toll!
    Das testscript sieht super aus! Auch mit transparenten PNGs!

    Jetzt werde ich versuchen das in das Hauptscript einzuarbeiten. Wenn es da keine größeren Probleme gibt, dann close ich das hier...


    VIELEN DANK @ Progandy & UEZ & Ahnungslos
    JStaxton

    edit: es scheint alles wunderbar zu funktionieren! Hab jetzt unterfunctionen, die eben schon Bilder vorbereiten in die "BackBuffer". Beim Redraw-können so dann ganze gruppen auf einmal gezeichnet werden, klasse... Warum der Aufwand? man merkt bei vielen Bildern schon einen Geschwindigkeitsunterschied!

    Einmal editiert, zuletzt von JStaxton (30. November 2009 um 19:08)