_GDIPlus_ImageLoadFromFile sperrt Bilddatei nach einladen, wie freigeben ?

  • Hallo,
    ich möchte einen Screenshot in meiner GUI als Hintergrund einladen, habe diesbezüglich mal nach Beispielen für PNG Bilder geschaut und bin fündig geworden.
    Allerdings kann ich die Bilddatei weder löschen, noch überschreiben wenn ich diese als Hintergrundbild geladen habe.
    Wie ich gelesen habe, liegt das daran das GDI+ die Bilddatei erst wieder freigibt, wenn ich diese im Programm nicht mehr benutze.

    Habe dann nach anderen Möglichkeiten geschaut, die Bilddatei zu laden.
    Konnte noch ein Beispiel finden wie man das PNG Bild in GUICtrlCreatePic lädt und danach auf die Datei zugreifen kann.
    Allerdings kann ich nun nicht mehr mit dem Windowshandle/Klasse auf die GUI und das dort angezeigte Bild zugreifen, benötige das Bild direkt in der GUI mit MY_WM_PAINT Funktion, damit das Bild auch bei minimierten Programm sichtbar ist und über Windowshandle/Klasse angesteuert werden kann.

    Wie kann ich dieses Beispiel so umändern, das ich nach dem Einladen der Datei Screenshot.png diese überschreiben/löschen kann ?

    Edit:
    Zwischenzeitlich habe ich rausgefunden das ich mit _GDIPlus_ImageDispose($hImage) das Bild freigeben kann, allerdings verschwindet es dann auch in der GUI.
    Als Notlösung könnte ich nun zwei Dateinamen im Wechsel nutzen:
    z.B. Screenshot-1.png als erstes einladen, dann einen neuen Screenshot als Screenshot-2.png erstellen und diesen in die GUI laden.
    Mittel _GDIPlus_ImageDispose($image) gebe ich das zuerst eingeladene Bild Screenshot-1.png wieder frei und kann dieses mit einem neuen Screenshot überschreiben.
    Das ganze dann im Dauerwechsel, würde gehen aber ist sicher nicht die optimale und richtige Lösung.

    Einmal editiert, zuletzt von Leisti86 (27. Oktober 2016 um 14:14)

  • Danke UEZ,
    hatte ich also das richtige gefunden :)
    Leider sitze ich nun schon ein paar Stunden rum und finde den Fehler nicht, bzw. konnte ich es nun auf _GDIPlus_ImageDispose($hImage) eingrenzen.

    Wenn ich während die Funktion ausgeführt wird das Fenster der GUI verschiebe oder schnell mit anderen Fenstern verdecke und wieder sichtbar mache, stürzt das ganze Programm ab :(
    Ebenso wenn ich ein Fenster eines anderen Programms minimiere/verkleinere, während die GUI dahinter ist.

    Ich vermute ich mache etwas bei _GDIPlus_ImageDispose($hImage) falsch ?

    Das sind die Funktionen die ich nutzen möchte, der Ablauf ist:
    1. GUI erstellen und mit Funktion _ReDraw verbinden (Bild soll auch wenn GUI von anderen Fenstern verdeckt ist angezeigt werden)
    2. PNG Bild in GUI laden und anzeigen.
    3. bei Bedarf geladenes PNG Bild wieder freigeben, damit dieses Überschrieben werden kann.
    4. neues PNG Bild einladen

    Scheint schwerer zu sein als ich dachte, ein Bild in einer GUI immer anzuzeigen, egal ob die GUI verdeckt ist oder minimiert.
    Wärst Du oder ein anderer Leser bitte so nett mir weiterzuhelfen ?

    Danke!

    So verwende ich die Funktionen bisher:

  • Nach einem _GDIPlus_ImageDispose($hImage) kannst du natürlich nicht mehr das Bild benutzen. Warum willst du das Bild freigeben, bevor das Skript beendet wird?

    Als Workaround könntest du das geladen Bild klonen und anschließend freigeben -> siehe dir dazu die Funktion _GDIPlus_BitmapCloneArea an.

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Hi,

    Wenn das Programm beim Fensterwechsel abstürzt könnte es daran liegen, dass $hImage zu dem Zeitpunkt auf kein Image verweist.
    Also musst du dafür sorgen, dass die Varriable $hImage immer auf ein gültiges Image verweisen oder du verhinderst das in der Funktion _ReDraw versucht wird dieses Image in der übergangszeit zu benützen.

    z.B. so würde die Varriable $hImage immer auf eine gültiges Image verweisen:

    AutoIt
    $hImageOld = $hImage; zwischenspeichern des Handles in $hImageOld
    $hImageNew = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\???.png"); laden des neunen Image
    If Not @error Then
       $hImage = $hImageNew; aktualisiere das Handle in $hImage
       _GDIPlus_ImageDispose($hImageOld); Gebe das alte Handle frei
    Else
       MsgBox(16, @ScriptName, "Image konnte nicht geladen werden :(")
    EndIf


    und zum Laden kannst du folgendes Prinzip verwenden (statt "_GDIPlus_ImageLoadFromFile"):

    AutoIt
    ; Fehlerabfragen, sinnvolle Funktionsbezeichnung sind nicht enthalten und müssten ergänzt werden!
    Func ExampleFunc($sPath)
       Local $hFile, $bImage, $hBitmap
       $hFile = FileOpen($sPath, $FO_BINARY); öffnet die Datei im binary/read Modus
       $bImage = FileRead($hFile); Liest den Inhalt der Datei aus
       FileClose($hFile); Gibt die Datei wieder frei
       $hBitmap = _GDIPlus_BitmapCreateFromMemory($bImage); Erstellt eine Bitmap anhand der eingelesenen Daten
       Return SetError(@error, @extended, $hBitmap)
    EndFunc

    Oder eben wie UEZ es geschrieben hat

    mfg
    Zeitriss