• Hi,

    ich fange einfach mal so an:

    Spoiler anzeigen
    [autoit]


    #include <GDIPlus.au3>

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

    Opt("GUIOnEventMode", True)

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

    $hWnd = GUICreate("GDI +", 250, 250)
    GUISetOnEvent(-3, "_Exit")
    GUISetState()

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

    _GDIPlus_Startup()

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

    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(250, 250, $hGraphics)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

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

    $hBrush = _GDIPlus_BrushCreateSolid(0xff0000ff) ;blau

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

    $hPen = _GDIPlus_PenCreate(0xffff00ff, 5) ;pink
    $hPen2 = _GDIPlus_PenCreate(0xffff00ff, 5) ;pink

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

    While True
    _GDIPlus_GraphicsClear($hBuffer, 0xffffffff)

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

    $iX = Random(0, 250 - 50, 1)
    $iY = Random(0, 250 - 50, 1)

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

    _GDIPlus_GraphicsFillRect($hBuffer, $iX, $iY, 50, 50, $hBrush)
    _GDIPlus_GraphicsDrawRect($hBuffer, $iX, $iY, 50, 50, $hPen)

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    Sleep(20)
    WEnd

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

    Func _Exit()
    Exit
    EndFunc

    [/autoit]

    Und jetzt die große Preisfrage... Was fehlt? :whistling:
    Genau: Das Freigeben der Ressourcen!

    Nun, das bedeutet jetzt: Das ganze Skript nochmal durchgehen, und alle geladenen Ressourcen einzeln wieder freigeben.

    Das ist mir beim GDI+-Rumspielen so auf den Nerv gegangen (Faulheit! :party: ), dass ich mir ein Skript geschrieben habe, welches eine Dispose-Funktion erstellt.^^

    GDI+ CleanUp.au3
    [autoit]


    #include <File.au3>
    #include <String.au3>

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

    $sFile = $CmdLine[1]
    $sDisposeFuncName = "_GDIPlus_DisposeAll"
    $sFunctionComment = "Common GDI+ Dispose Function, created with 'GDI+ CleanUp.au3'"

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

    $iReplCounter = 0
    Local $aLines[1]
    _FileReadToArray($sFile, $aLines)

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

    $sCode = FileRead($sFile)
    If StringInStr($sCode, "Func " & $sDisposeFuncName & "()" & @CRLF) Then
    $sFunctionCode = _StringBetween($sCode, "Func " & $sDisposeFuncName & "()", "EndFunc")
    $sCode = StringReplace($sCode, @CRLF & @CRLF &"Func " & $sDisposeFuncName & "()" & $sFunctionCode[0] & "EndFunc", "")
    EndIf

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

    $sExitFuncCode = "Func " & $sDisposeFuncName & "()" & @CRLF & @TAB & ";" & $sFunctionComment & @CRLF

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

    For $iLine = 1 To $aLines[0]
    $sLine = StringRegExpReplace($aLines[$iLine], """(.+)""", "", 1)

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

    If Not StringInStr($sLine, "=") Then ContinueLoop ;Keine Ressource wurde erstellt -> Abbruch

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

    $aLR = StringSplit($sLine, "=", 2)
    $sVar = StringStripWS($aLR[0], 8)
    $sCommandLine = StringStripWS($aLR[1], 8)
    If StringLeft($sCommandLine, 9) <> "_GDIPlus_" Then ContinueLoop ;Keine GDIPlus-Zeile -> Abbruch
    $iReplCounter += 1
    $aTMP = StringSplit($sCommandLine, "(", 2)
    $sCommand = $aTMP[0]
    ;Bestimmen, welche Art von Ressource vorliegt...

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

    Switch $sCommand
    Case "_GDIPlus_GraphicsCreateFromHWND", "_GDIPlus_GraphicsCreateFromHDC", "_GDIPlus_ImageGetGraphicsContext"
    ;Graphics
    $sDisposeCommand = "_GDIPlus_GraphicsDispose"
    Case "_GDIPlus_BitmapCreateFromFile", "_GDIPlus_BitmapCreateFromGraphics", "_GDIPlus_BitmapCreateFromHBITMAP", "_GDIPlus_BitmapCreateHBITMAPFromBitmap"
    ;Bitmaps
    $sDisposeCommand = "_GDIPlus_BitmapDispose"
    Case "_GDIPlus_ImageLoadFromFile"
    ;Images
    $sDisposeCommand = "_GDIPlus_ImageDispose"
    Case "_GDIPlus_BrushCreateSolid"
    ;Brushes
    $sDisposeCommand = "_GDIPlus_BrushDispose"
    Case "_GDIPlus_PenCreate"
    ;Pens
    $sDisposeCommand = "_GDIPlus_PenDispose"
    Case "_GDIPlus_FontCreate"
    ;Fonts
    $sDisposeCommand = "_GDIPlus_FontDispose"
    Case "_GDIPlus_FontFamilyCreate"
    ;FontFamilies
    $sDisposeCommand = "_GDIPlus_FontFamilyDispose"
    Case "_GDIPlus_MatrixCreate"
    ;Matrizen
    $sDisposeCommand = "_GDIPlus_MatrixDispose"
    Case "_GDIPlus_StringFormatCreate"
    ;StringFormat
    $sDisposeCommand = "_GDIPlus_StringFormatDispose"
    Case "_GDIPlus_ArrowCapCreate"
    ;ArrowCaps
    $sDisposeCommand = "_GDIPlus_ArrowCapDispose"
    Case Else
    ;Befehl nicht bekannt...
    ContinueLoop
    EndSwitch

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

    $sExitFuncCode &= @TAB & $sDisposeCommand & "(" & $sVar & ")" & @CRLF
    ;~ ConsoleWrite("GDIPlus line found @ " & $iLine & " with: " & $sCommand & @CRLF)
    Next

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

    $sExitFuncCode &= @TAB & "_GDIPlus_Shutdown()" & @CRLF & "EndFunc"

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

    $sCode &= @CRLF & @CRLF & $sExitFuncCode

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

    $hFile = FileOpen($sFile, 2)
    FileWrite($hFile, $sCode)
    FileClose($hFile)

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

    ConsoleWrite(StringFormat("+> Es wurden %i Ressourcen verarbeitet.\n+> Dispose-Funktion: %s\n", $iReplCounter, $sDisposeFuncName))

    [/autoit]


    Bei Gelegenheit könnte man das auch noch auf die WinAPI und DllStruct's erweitern...
    Generell ist das ganze noch verbesserungswürdig, aber das kommt noch. Betrachtet es als "Beta".^^

    Nach CleanUp
    [autoit]


    #include <GDIPlus.au3>

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

    Opt("GUIOnEventMode", True)

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

    $hWnd = GUICreate("GDI +", 250, 250)
    GUISetOnEvent(-3, "_Exit")
    GUISetState()

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

    _GDIPlus_Startup()

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

    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics(250, 250, $hGraphics)
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

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

    $hBrush = _GDIPlus_BrushCreateSolid(0xff0000ff) ;blau

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

    $hPen = _GDIPlus_PenCreate(0xffff00ff, 5) ;pink
    $hPen2 = _GDIPlus_PenCreate(0xffff00ff, 5) ;pink

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

    While True
    _GDIPlus_GraphicsClear($hBuffer, 0xffffffff)

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

    $iX = Random(0, 250 - 50, 1)
    $iY = Random(0, 250 - 50, 1)

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

    _GDIPlus_GraphicsFillRect($hBuffer, $iX, $iY, 50, 50, $hBrush)
    _GDIPlus_GraphicsDrawRect($hBuffer, $iX, $iY, 50, 50, $hPen)

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    Sleep(20)
    WEnd

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

    Func _Exit()
    _GDIPlus_DisposeAll()
    Exit
    EndFunc

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

    Func _GDIPlus_DisposeAll()
    ;Common GDI+ Dispose Function, created with 'GDI+ CleanUp.au3'
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_PenDispose($hPen2)
    _GDIPlus_Shutdown()
    EndFunc

    [/autoit]


    Der Dispose-Funktionsname und der Kommentar lassen sich im Skript natürlich anpassen (#ToDo: In INI auslagern und Konfigurationsoberfläche implementieren).^^

    Was natürlich noch fehlt:
    Die Einbindung in SciTE (Hier ein Danke an BugFix, ohne den wäre ich an dem Lua-Kram gescheitert :D).
    SciTEUser.properties

    Code
    command.name.36.$(au3)=GDI+ CleanUp
    command.36.*.au3="$(autoit3dir)\autoit3.exe" "$(SciteDefaultHome)\GDI+ CleanUp.au3" "$(FilePath)"
    command.mode.36.*=savebefore:yes
    command.shortcut.36.*.au3=Ctrl+Alt+G


    Gegebenenfalls dann den Pfad anpassen (Hier würde die Datei im SciTE-Ordner liegen).^^

    Have Fun,

    chess

    • Offizieller Beitrag

    3 Punkte:
    • Du gehst in deinem Skript ausschließlich von Globalen Handles aus. Es gibt viele Fälle, in denen Handle Local in Funktionen erstellt werden und auch dort wieder sauber geclosed werden sollten. Eine entsprechende Unterscheidung wäre sinnvoll. Wie du Local von Global/Dim trennst, kannst du dir z.B. hier (ab Zeile 135) anschauen.
    • Der Aufruf für die Dispose-Funktion wird ja vor einem (evtl. auch mehreren) Exit im Skript eingefügt. Ich finde aber in dem Skript nicht die Suche nach "Exit" -- oder habe ich was übersehen?
    • Ich würde auf Nummer sicher gehen und jeden Dispose-Befehl nur ausführen, wenn das Handle auch noch existiert - also "If IsHwnd($Handle) Then ...". Damit sparst du dir auch vorab zu prüfen, ob schon ein Dispose-Befehl für das Handle existiert.

  • Punkt 1:
    Das war eine der Sachen, die ich noch geplant hatte.^^
    Punkt 2:
    Genau deswegen wird eine _GDIPlus_DisposeAll-Funktion erzeugt, die dann selbst an entsprechenden Punkt aufgerufen werden kann, wie ich das schon oben gemacht habe. Ich dachte, das überlasse ich lieber dem Programmierer. ^^
    Punkt 3:
    Wieso sollte IsHWnd bei einem GDI+-Objekt True zurück geben? 8|
    HWnd ist doch hWindow, also ein Fensterhandle, oder?

    lg^^

    • Offizieller Beitrag

    Stimmt ja - GDI+ Handle sind weder identifizier- noch validierbar. Ist ein String-Handle, dass auch nach dem Dispose unverändert von der Variable gehalten wird. Nur im internen GDI+ Management wird das Handle beim Dispose gelöscht.
    Naja, dann eben einmal öfter disposen, falls schon im Skript getan. Schadet jedenfalls nicht. ;)