GDIplus: Frage zu GraphicsDispose, etc

  • Hi.
    Ich bekomme bei GDIplus die Grafik nicht wieder gelöscht. Zumindest nicht solange ein weiteres Fenster drüber geschoben wird.
    Das script fürs Bild sieht so aus:

    [autoit]


    $Bildschirm=_WinAPI_GetDesktopWindow()
    $WindowDC=_WinAPI_GetWindowDC($Bildschirm)
    _GDIPlus_Startup()
    $Grafik=_GDIPlus_GraphicsCreateFromHDC($WindowDC)
    $Bild = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Target.ico")
    _GDIPlus_GraphicsDrawImage($Grafik, $Bild,8,8)

    [/autoit]

    Und um alle Bilder zu löschen habe ich versucht _GraphicsDispose und _BitmapDispose zu starten, aber ohne erfolg.
    Könnte es funktionieren, wenn ich ein Transparentes Bild über die Grafik lege, damit der Bildschirm sich zumindest wieder Aktualisiert und die Grafiken verschwinden?

    Einmal editiert, zuletzt von Taliis (10. März 2012 um 18:44)

  • Abend,

    du könntest _GDIPlus_GraphicsClear verwenden

    Spoiler anzeigen
    [autoit]


    2
    3
    4
    5
    6
    $Bildschirm=_WinAPI_GetDesktopWindow()
    $WindowDC=_WinAPI_GetWindowDC($Bildschirm)
    _GDIPlus_Startup()
    $Grafik=_GDIPlus_GraphicsCreateFromHDC($WindowDC)
    $Bild = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Target.ico")
    _GDIPlus_GraphicsDrawImage($Grafik, $Bild,8,8)
    _GDIPlus_GraphicsClear($Grafik,0xFFFFFF)

    [/autoit]
  • Es ist nicht sehr empfehlenswert direkt auf das Desktopfenster zu zeichnen... Sonst versuchen nämlich Windows und dein Programm zu verschiedenen Zeiten das Bild zu aktualisieren und kommen sich in die Quere.
    Und ein Transparentes Bild wird dein Problem auch nicht lösen. Je nach Modus würde GDI+ entweder die darunterliegenden Pixel auf den Farbwert 0 setzen (schwarzes Rechteck), oder gar nichts verändern (transparent auf Rot ist immer noch Rot ;)).
    Mach lieber ein Mehrschichtiges transparentes Fenster über den ganzen Desktop, oder die gewünschte Stelle und zeichne da drauf herum. Dann kannst du die Grafik auch mit GraphicsClear($hGraphics, 0) wieder "zurücksetzen".
    Ich hab dazu mal ein Beispiel gemacht.

  • Ich weiß, dass es nicht optimal ist, direkt auf dem Bildschirm zu Zeichnen.
    Es dient lediglich zur Verdeutlichung, der Positions Koordinaten und wird nach ein paar Sekunden wieder entfernt.
    _GDIPlus_GraphicsClear($Grafik,0xFFFFFF)
    Funktioniert nicht so gut. Der ganze Bildschirm ist danach schwarz.

    Ich lass es jetzt einfach wie es war und autoit startet das Fenster danach einfach neu.
    Ist immerhin weniger Arbeit als ein transparentes GUI drüber zu legen.

  • Zitat

    und wird nach ein paar Sekunden wieder entfernt.


    Nein. Es wird genau dann entfernt wenn Wndows es will, also wenn du etwas anderes dadrüber Positionierst. Wie z.B. das Auswahlrechteck oder ein Fenster..

    Zitat

    Ich lass es jetzt einfach wie es war und autoit startet das Fenster danach einfach neu.


    Wie denn das?

    Zitat

    Ist immerhin weniger Arbeit als ein transparentes GUI drüber zu legen.


    Nicht wirklich.. An meinem Script müsste man nicht viel anpassen um das zu ändern. Abgesehen davon hätte ich dir dabei auch helfen können.

  • Hi,
    du könntest ein eigenes GUI machen durch das man durch drücken kann und das bei einer bestimmen Farbe alles löscht, bzw. transparent setzt.

    So könnte man das machen:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <timers.au3>
    #include <misc.au3>
    #Include <WinAPI.au3>

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

    Global Const $GWL_EXSTYLE = -20

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

    $dll = DllOpen("user32.dll")

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

    Global $ballpos1=@DesktopWidth/2
    Global $ballpos2=@DesktopHeight/2
    Global $BewegungSenkrecht=Random(5, 7, 1)
    Global $BewegungWagrecht=Random(5, 7, 1)
    Global $Speed=10

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

    _GDIPlus_Startup()

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

    Global $hGui = GUICreate("Rahmen", @DesktopWidth, @DesktopHeight, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
    GUISetBkColor(0xABCDEF)
    _WinAPI_SetLayeredWindowAttributes($hGui, 0xABCDEF, 255)
    GUISetState()
    Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)
    $Pinsel = _GDIPlus_PenCreate(0xFF0000FF, 20)
    Global $vanish = _GDIPlus_PenCreate(0xFF000000, 20)
    ;Global $vanish = _GDIPlus_PenCreate(0xFFABCDEF, 20) // Alles mit der Farbe ABCDEF verschwindet
    ;_GDIPlus_GraphicsClear ( $hGraphic, 0xFFABCDEF ) // Wenn du hier mit drübermalst ist alles weg
    $t1 = _Timer_SetTimer(0, 20, "move")
    $begin=TimerInit()

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

    _Win_SetClickThrough($hGui)

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

    While 1
    $nmsg=GUIGetMsg()
    Switch $nmsg
    Case $gui_event_close
    Exit
    EndSwitch
    WEnd

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

    Func _ende()
    _GDIPlus_GraphicsClear ( $hGraphic, 0xFFABCDEF )
    _GDIPlus_PenDispose($Pinsel)
    _GDIPlus_PenDispose($vanish)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_ende

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

    Func move($a, $b, $c, $d)
    _GDIPlus_GraphicsDrawArc ( $hGraphic, $ballpos1, $ballpos2, 70, 70, 180, 360, $vanish )
    $ballpos1+=$BewegungWagrecht * $Speed
    $ballpos2+=$BewegungSenkrecht * $Speed
    _GDIPlus_GraphicsDrawArc ( $hGraphic, $ballpos1, $ballpos2, 70, 70, 180, 360, $Pinsel )
    If $ballpos1 >= @DesktopWidth - 80 And $BewegungWagrecht > 0 Then $BewegungWagrecht = Random(-7, -5, 1)
    If $ballpos1 < 10 And $BewegungWagrecht < 0 Then $BewegungWagrecht = Random(5, 7, 1)
    If $ballpos2 >= @DesktopHeight - 95 And $BewegungSenkrecht > 0 Then $BewegungSenkrecht = Random(-7, -5, 1)
    If $ballpos2 < 30 And $BewegungSenkrecht < 0 Then $BewegungSenkrecht = Random(5, 7, 1)
    If _GDIPlus_PenGetColor ( $vanish )=0xFF000000 Then
    _GDIPlus_PenSetColor ( $vanish, 0xFFFFFF00 )
    ElseIf _GDIPlus_PenGetColor ( $vanish )=0xFFFFFF00 Then
    _GDIPlus_PenSetColor ( $vanish, 0xFFFF0000 )
    ElseIf _GDIPlus_PenGetColor ( $vanish )=0xFFFF0000 Then
    _GDIPlus_PenSetColor ( $vanish, 0xFF00FF00 )
    ElseIf _GDIPlus_PenGetColor ( $vanish )=0xFF00FF00 Then
    _GDIPlus_PenSetColor ( $vanish, 0xFF000000 )
    EndIf
    $dif=TimerDiff( $begin )
    If $dif>12000 Then
    _GDIPlus_GraphicsClear ( $hGraphic, 0xFFABCDEF )
    $begin=TimerInit()
    EndIf
    EndFunc ;==>move

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

    Func _Win_SetClickThrough($title,$text = "",$noclic = True)
    ; UDF von ProgAndy
    Local $hWnd = WinGetHandle($title,$text)
    If @error Then Return SetError(1,0,0)
    If $noclic Then
    _WinAPI_SetWindowLong($hWnd,$GWL_EXSTYLE,BitOR(_WinAPI_GetWindowLong($hWnd,$GWL_EXSTYLE),$WS_EX_TRANSPARENT))
    If @error Then Return SetError(2,0,0)
    ;WinSetTrans($hWnd,"",255) ; Sets the Layered Attribute, but still shows the window :) Hier müsste man checken ob es das attribute schon, habs mal auskommentiert
    If @error Then Return SetError(2,0,0)
    Else
    _WinAPI_SetWindowLong($hWnd,$GWL_EXSTYLE,BitAND(_WinAPI_GetWindowLong($hWnd,$GWL_EXSTYLE),BitNOT($WS_EX_TRANSPARENT)))
    If @error Then Return SetError(2,0,0)
    EndIf
    Return 1
    EndFunc

    [/autoit]

    Gruß Greek

  • Genau das meinte ich.
    Der Script ist schon länger als mein ganzes Modul.

    Das was ich im Moment baue, ist nur als Firststart gedacht, weil es im Programm, welches automatisiert werden soll 2 Tabs gibt, die nicht mit Tastatur
    bedient werden können. Da aber fast jeder ein anderes Windows aussehen hat, brauche ich die exakten Koordinaten.
    Beispiel: Klassischer Skin und Standard XP skin.