WM_PAINT zeigt seltsames Verhalten

  • Hallöchen,

    ich habe folgendes Problem entdeckt:

    Die per GDI+ auf eine GUI gezeichneten Objekte verschwinden ja bekanntlich, wenn das Fenster minimiert wird etc...
    Um das zu umgehen gibt es im Netz genug Lösungen, in denen die WM_PAINT-Message der GUI abgefangen und alles neu gezeichnet wird. So weit so gut, doch bei mir wollte das einfach nicht klappen. Ich entwickle gerade ein größeres Projekt, da kann sich ja leicht ein Fehler einschleichen, dachte ich mir... Also hab ich weiter nach Lösungen gesucht und geguckt, was ich falsch mache.

    >Hier< war ein relativ simples Programm zum Neuzeichnen per WM_PAINT verfasst. Doch jetzt der Witz: Das funktionierte ebenfalls nicht! ^^ Nach einiger Zeit habe ich dann (mehr oder weniger durch Zufall) die Lösung gefunden: In der WM_PAINT-Funktion muss am Anfang ein Sleep(...) eingebaut werden! 8| Wieso auch immer, aber dann funktionierte auch mein größeres Projekt...

    Da die Lösung mich ziemlich verwirrt und ich das Sleep nicht unbedingt verwenden möchte, wollte ich mal die Experten um Rat fragen ^^
    Also: Wieso klappt das folgende Beispiel nur, wenn das "Sleep(10)" in Zeile 29 nicht auskommentiert ist? Und wie kann ich das auch ohne Sleep lösen?

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

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

    Opt("GUIOnEventMode", 1)
    OnAutoItExitRegister("_Exit")

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

    _GDIPlus_Startup()

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

    Global $iWidth = 400, $iHeight = 400

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

    $hGUI = GUICreate("GDI+ Tut", $iWidth, $iHeight)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)

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

    GUISetOnEvent(-3, "_Exit")
    GUIRegisterMsg(0x000F,"WM_PAINT")
    GUISetState()

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

    While 1 * Sleep(10)
    WEnd

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

    Func _Exit()
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

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

    Func WM_PAINT()
    ;Sleep(10)
    _GDIPlus_GraphicsFillRect($hGraphic,100,100,200,200,$hBrush)
    EndFunc

    [/autoit]

    PS: Betriebssystem = Windows 7 x64

    Danke schonmal für eure Hilfe ^^

    MM

    Einmal editiert, zuletzt von MadMushroom (9. Dezember 2014 um 19:43)

  • Man sollte niemals ein sleep in einer Callback-Funktion verwenden (müssen).
    Bei deinem Problem hilft dir WM_ERASEBKGND weiter.

    Weiters empfehle ich dir, immer mit einem Backbuffer zu arbeiten.
    Das Neuzeichnen des Fensters geht schneller und es flackert nicht.


    [autoit]

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

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

    Opt("GUIOnEventMode", 1)
    Opt("MustDeclareVars", 1)

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

    Global $iWidth = 400, $iHeight = 400

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

    _GDIPlus_Startup()
    Global $hGUI = GUICreate("GDI+ Tut", $iWidth, $iHeight)
    GUISetOnEvent(-3, "_Exit")

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

    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)

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

    Global $hBmp_Buffer = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
    Global $hGfx_Buffer = _GDIPlus_ImageGetGraphicsContext($hBmp_Buffer)
    _GDIPlus_GraphicsClear($hGfx_Buffer, 0xFFFFFFFF)
    _GDIPlus_GraphicsSetSmoothingMode($hGfx_Buffer, 2)

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

    Global $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    _GDIPlus_GraphicsFillRect($hGfx_Buffer, 100, 100, 200, 200, $hBrush)
    _GDIPlus_BrushDispose($hBrush)

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

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

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

    While Sleep(10)
    WEnd

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

    Func _Exit()
    _GDIPlus_GraphicsDispose($hGfx_Buffer)
    _GDIPlus_BitmapDispose($hBmp_Buffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

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

    Func WM_PAINT()
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmp_Buffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func WM_ERASEBKGND()
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmp_Buffer, 0, 0)
    Return True
    EndFunc ;==>WM_ERASEBKGND

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

    E

  • Man sollte niemals ein sleep in einer Callback-Funktion verwenden (müssen).
    Bei deinem Problem hilft dir WM_ERASEBKGND weiter.

    Danke eukalyptus, deine Lösung hat mir prima geholfen! :thumbup:
    Funktioniert einwandfrei. Und die Idee mit dem Backbuffer ist auch ganz praktisch. :)

    MM