GDI+ und Controls

  • Guten Tag. ;D

    Da ich ein ziemlicher Noob auf dem Bereich bin und hier sicher viele Kenner unterwegs sind, wollte ich mal etwas 'grundlegendes' fragen.
    Also... Wie geht man am besten mit den Controls (Inputs, Buttons usw) um, wenn man gleichzeitig auf derselben Fläche (Hintergrund) Grafiken mit GDI+ zeichnet?

    Wenn ich die Controls direkt in der GUI erstelle, werden sie ja logischerweise übermalt.
    Wenn ich sie aber auf einer bzw. mehreren Child-GUI's erstelle, dann verliert die Parent-GUI bei Eingaben ihren Fokus,
    was unschön und ungünstig ist, weil der Parent in meinem Fall immer Events empfangen muss (Mausklicks u. ä.).

    Welche Lösungen gäbe es denn dafür?

    LG

    Einmal editiert, zuletzt von $var (5. Juni 2012 um 22:44)

  • Das ist eine sehr schöne Funktion und klappt soweit, so wie ich es mir wünsche.

    Doch wie ist es, wenn ich die Buttons ausblenden will? In dem Bereich wird ja nicht mehr gezeichnet.
    Wie kann ich es wieder 'unsetten'?

    €:

    [autoit]

    $iCombineMode = 0

    [/autoit]

    Das hätte ich mir durchlesen sollen. Sorry. .__.

    Vielen Dank! :thumbup:

  • Ich melde mich nun wieder.

    Leider komme ich mit der Funktion nicht zurecht.
    Wenn ich sie gleich nach der Erstellung des Inputs anwende, funktioniert es perfekt.
    Rufe ich die Funktion aber später auf (siehe Beispielscript #2), scheint es irgendwie zu spinnen...
    Es blinkt die ganze Zeit. Sprich: es wird übermalt. Manchmal verschwindet in dem angegebenen Bereich die obere der beiden verwendeten Grafiken.
    Ich kann es nicht wirklich erklären, da ich es einfach nicht verstehe.

    Im Anhang sind zwei Dummygrafiken, die ich für eine genaue Nachstellung der Situation gemacht habe.

    Im ersten Script benutze ich die Funktion am Anfang und erhalte den gewünschten Effekt.

    Beispiel #1 - Funktioniert
    [autoit]

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

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

    _GDIPlus_Startup ()
    Opt ("GUIOnEventMode", 1)

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

    Global Const $i_WIDTH = 640, $i_HEIGHT = 680

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

    Global $h_Gui = GUICreate ("", $i_WIDTH, $i_HEIGHT)
    Global $h_Input = GUICtrlCreateInput ("", 36, 623, 564, 14, Default, 0x00000020)

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

    Global $h_Graphic = _GDIPlus_GraphicsCreateFromHWND ($h_Gui)
    Global $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics ($i_WIDTH, $i_HEIGHT, $h_Graphic)
    Global $h_Backbuffer = _GDIPlus_ImageGetGraphicsContext ($h_Bitmap)

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

    Global $h_Dummy1 = _GDIPlus_ImageLoadFromFile ('dummylayer1.png')
    Global $h_Dummy2 = _GDIPlus_ImageLoadFromFile ('dummylayer2.png')

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

    ;GUICtrlSetState ($h_Input, 32) ; 32 == $GUI_HIDE
    _GDIPlus_GraphicsSetClipRect ($h_Backbuffer, 36, 623, 564, 14, 3)

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

    GUIRegisterMsg (0x000F, "WM_PAINT")
    GUISetOnEvent (-3, "_Exit", $h_Gui)
    GUISetOnEvent (-7, "_PrimaryDown", $h_Gui)
    OnAutoItExitRegister ("_OnExit")
    GUISetState (@SW_SHOW, $h_Gui)

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

    While Sleep (25)
    _GDIPlus_GraphicsClear ($h_Backbuffer, 0xFF00FF00)
    _GDIPlus_GraphicsDrawImage ($h_Backbuffer, $h_Dummy1, 0, 0)
    _GDIPlus_GraphicsDrawImage ($h_Backbuffer, $h_Dummy2, 0, 0)
    _WinAPI_RedrawWindow ($h_Gui, 0, 0, $RDW_INTERNALPAINT)
    WEnd

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

    Func _PrimaryDown ()
    Local $a_Pos = GUIGetCursorInfo ($h_Gui)
    If IsArray ($a_Pos) Then
    Select
    Case _InRect ($a_Pos, 36, 623, 564, 14)
    ;GUICtrlSetState ($h_Input, 16) ; 16 == $GUI_SHOW
    ;_GDIPlus_GraphicsSetClipRect ($h_Backbuffer, 36, 623, 564, 14, 3)
    EndSelect
    EndIf
    EndFunc ;==> _PrimaryDown

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

    Func _GDIPlus_GraphicsSetClipRect ($hGraphics, $nX, $nY, $nWidth, $nHeight, $iCombineMode = 0)
    Local $aResult = DllCall ($ghGDIPDll, "uint", "GdipSetClipRect", "hwnd", $hGraphics, "float", $nX, "float", $nY, "float", $nWidth, "float", $nHeight, "int", $iCombineMode)
    If @error Then Return SetError (@error, @extended, False)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[0] = 0
    EndFunc ;==> _GDIPlus_GraphicsSetClipRect

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

    Func _InRect ($aPoint, $iXRect, $iYRect, $iWidthRect, $iHeightRect)
    If $aPoint[0] >= $iXRect And $aPoint[1] >= $iYRect And $aPoint[0] <= $iXRect + $iWidthRect And $aPoint[1] <= $iYRect + $iHeightRect Then Return 1
    Return 0
    EndFunc ;==> _InRect

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

    Func WM_PAINT ()
    _GDIPlus_GraphicsDrawImageRect ($h_Graphic, $h_Bitmap, 0, 0, $i_WIDTH, $i_HEIGHT)
    EndFunc ;==> WM_PAINT

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

    Func _Exit ()
    Exit
    EndFunc ;==> _Exit

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

    Func _OnExit ()
    _GDIPlus_GraphicsDispose ($h_Graphic)
    _GDIPlus_BitmapDispose ($h_Bitmap)
    _GDIPlus_Shutdown ()
    EndFunc ;==> _OnExit

    [/autoit]


    In diesem Script will ich den Input erst beim Klick auf den hellblauen Bereich anzeigen lassen, was jedoch nicht klappt.

    Beispiel #2 - Funktioniert nicht
    [autoit]

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

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

    _GDIPlus_Startup ()
    Opt ("GUIOnEventMode", 1)

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

    Global Const $i_WIDTH = 640, $i_HEIGHT = 680

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

    Global $h_Gui = GUICreate ("", $i_WIDTH, $i_HEIGHT)
    Global $h_Input = GUICtrlCreateInput ("", 36, 623, 564, 14, Default, 0x00000020)

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

    Global $h_Graphic = _GDIPlus_GraphicsCreateFromHWND ($h_Gui)
    Global $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics ($i_WIDTH, $i_HEIGHT, $h_Graphic)
    Global $h_Backbuffer = _GDIPlus_ImageGetGraphicsContext ($h_Bitmap)

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

    Global $h_Dummy1 = _GDIPlus_ImageLoadFromFile ('dummylayer1.png')
    Global $h_Dummy2 = _GDIPlus_ImageLoadFromFile ('dummylayer2.png')

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

    GUICtrlSetState ($h_Input, 32) ; 32 == $GUI_HIDE
    ;_GDIPlus_GraphicsSetClipRect ($h_Backbuffer, 36, 623, 564, 14, 3)

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

    GUIRegisterMsg (0x000F, "WM_PAINT")
    GUISetOnEvent (-3, "_Exit", $h_Gui)
    GUISetOnEvent (-7, "_PrimaryDown", $h_Gui)
    OnAutoItExitRegister ("_OnExit")
    GUISetState (@SW_SHOW, $h_Gui)

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

    While Sleep (25)
    _GDIPlus_GraphicsClear ($h_Backbuffer, 0xFF00FF00)
    _GDIPlus_GraphicsDrawImage ($h_Backbuffer, $h_Dummy1, 0, 0)
    _GDIPlus_GraphicsDrawImage ($h_Backbuffer, $h_Dummy2, 0, 0)
    _WinAPI_RedrawWindow ($h_Gui, 0, 0, $RDW_INTERNALPAINT)
    WEnd

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

    Func _PrimaryDown ()
    Local $a_Pos = GUIGetCursorInfo ($h_Gui)
    If IsArray ($a_Pos) Then
    Select
    Case _InRect ($a_Pos, 36, 623, 564, 14)
    GUICtrlSetState ($h_Input, 16) ; 16 == $GUI_SHOW
    _GDIPlus_GraphicsSetClipRect ($h_Backbuffer, 36, 623, 564, 14, 3) ; <== Funktioniert nicht so, wie geplant.
    EndSelect
    EndIf
    EndFunc ;==> _PrimaryDown

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

    Func _GDIPlus_GraphicsSetClipRect ($hGraphics, $nX, $nY, $nWidth, $nHeight, $iCombineMode = 0)
    Local $aResult = DllCall ($ghGDIPDll, "uint", "GdipSetClipRect", "hwnd", $hGraphics, "float", $nX, "float", $nY, "float", $nWidth, "float", $nHeight, "int", $iCombineMode)
    If @error Then Return SetError (@error, @extended, False)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[0] = 0
    EndFunc ;==> _GDIPlus_GraphicsSetClipRect

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

    Func _InRect ($aPoint, $iXRect, $iYRect, $iWidthRect, $iHeightRect)
    If $aPoint[0] >= $iXRect And $aPoint[1] >= $iYRect And $aPoint[0] <= $iXRect + $iWidthRect And $aPoint[1] <= $iYRect + $iHeightRect Then Return 1
    Return 0
    EndFunc ;==> _InRect

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

    Func WM_PAINT ()
    _GDIPlus_GraphicsDrawImageRect ($h_Graphic, $h_Bitmap, 0, 0, $i_WIDTH, $i_HEIGHT)
    EndFunc ;==> WM_PAINT

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

    Func _Exit ()
    Exit
    EndFunc ;==> _Exit

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

    Func _OnExit ()
    _GDIPlus_GraphicsDispose ($h_Graphic)
    _GDIPlus_BitmapDispose ($h_Bitmap)
    _GDIPlus_Shutdown ()
    EndFunc ;==> _OnExit

    [/autoit]

    Ich entschuldige mich für den unordentlichen Code. Habe da etwas herumgetestet... ~,~
    Wäre nett, wenn jemand mal drüberschauen könnte... Ich verstehe es nämlich überhaupt nicht.

  • Sorry, ich hab deinen Thread irgendwie vergessen... ^^
    Problem gelöst:

    Spoiler anzeigen
    [autoit]

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

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

    _GDIPlus_Startup ()
    Opt ("GUIOnEventMode", 1)

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

    Global Const $i_WIDTH = 640, $i_HEIGHT = 680

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

    Global $h_Gui = GUICreate ("", $i_WIDTH, $i_HEIGHT)
    Global $h_Input = GUICtrlCreateInput ("", 36, 623, 564, 14, Default, 0x00000020)

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

    Global $h_Graphic = _GDIPlus_GraphicsCreateFromHWND ($h_Gui)
    Global $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics ($i_WIDTH, $i_HEIGHT, $h_Graphic)
    Global $h_Backbuffer = _GDIPlus_ImageGetGraphicsContext ($h_Bitmap)

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

    Global $h_Dummy1 = _GDIPlus_ImageLoadFromFile ('dummylayer1.png')
    Global $h_Dummy2 = _GDIPlus_ImageLoadFromFile ('dummylayer2.png')

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

    GUICtrlSetState ($h_Input, 32) ; 32 == $GUI_HIDE
    ;_GDIPlus_GraphicsSetClipRect ($h_Backbuffer, 36, 623, 564, 14, 3)

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

    GUIRegisterMsg (0x000F, "WM_PAINT")
    GUISetOnEvent (-3, "_Exit", $h_Gui)
    GUISetOnEvent (-7, "_PrimaryDown", $h_Gui)
    OnAutoItExitRegister ("_OnExit")
    GUISetState (@SW_SHOW, $h_Gui)

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

    While Sleep (25)
    _GDIPlus_GraphicsClear ($h_Backbuffer, 0xFF00FF00)
    _GDIPlus_GraphicsDrawImage ($h_Backbuffer, $h_Dummy1, 0, 0)
    _GDIPlus_GraphicsDrawImage ($h_Backbuffer, $h_Dummy2, 0, 0)
    _WinAPI_RedrawWindow ($h_Gui, 0, 0, $RDW_INTERNALPAINT)
    WEnd

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

    Func _PrimaryDown ()
    Local $a_Pos = GUIGetCursorInfo ($h_Gui)
    If IsArray ($a_Pos) Then
    Select
    Case _InRect ($a_Pos, 36, 623, 564, 14)
    GUICtrlSetState ($h_Input, 16) ; 16 == $GUI_SHOW
    _GDIPlus_GraphicsClear ($h_Backbuffer, 0)
    _GDIPlus_GraphicsSetClipRect ($h_Backbuffer, 36, 623, 564, 14, 3) ; <== Funktioniert nicht so, wie geplant.
    EndSelect
    EndIf
    EndFunc ;==> _PrimaryDown

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

    Func _GDIPlus_GraphicsSetClipRect ($hGraphics, $nX, $nY, $nWidth, $nHeight, $iCombineMode = 0)
    Local $aResult = DllCall ($ghGDIPDll, "uint", "GdipSetClipRect", "hwnd", $hGraphics, "float", $nX, "float", $nY, "float", $nWidth, "float", $nHeight, "int", $iCombineMode)
    If @error Then Return SetError (@error, @extended, False)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[0] = 0
    EndFunc ;==> _GDIPlus_GraphicsSetClipRect

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

    Func _InRect ($aPoint, $iXRect, $iYRect, $iWidthRect, $iHeightRect)
    If $aPoint[0] >= $iXRect And $aPoint[1] >= $iYRect And $aPoint[0] <= $iXRect + $iWidthRect And $aPoint[1] <= $iYRect + $iHeightRect Then Return 1
    Return 0
    EndFunc ;==> _InRect

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

    Func WM_PAINT ()
    _GDIPlus_GraphicsDrawImageRect ($h_Graphic, $h_Bitmap, 0, 0, $i_WIDTH, $i_HEIGHT)
    EndFunc ;==> WM_PAINT

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

    Func _Exit ()
    Exit
    EndFunc ;==> _Exit

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

    Func _OnExit ()
    _GDIPlus_GraphicsDispose ($h_Graphic)
    _GDIPlus_GraphicsDispose ($h_Backbuffer)
    _GDIPlus_BitmapDispose ($h_Bitmap)
    _GDIPlus_Shutdown ()
    EndFunc ;==> _OnExit

    [/autoit]


    SetClipRect beeinflusst alle Funktionen die auf diese Grafik zugreifen, nicht die Grafik selbst. In deinem Fall wird die Bitmap vor der Funktion bereits komplett ausgemalt. Wenn du jetzt eine neue ClipRegion für den Backbuffer (die Grafik der Bitmap) festlegst, wird nichts mehr in diesem Bereich gezeichnet, aber die Bitmap ist an dieser Stelle trotzdem noch ausgefüllt. Du hast zwar einen Bereich der Grafik sozusagen gesperrt, aber nicht wieder auf transparent gesetzt (nur komplett transparente Bereiche (Alphachannel = 0) beeinflussen die Controls nicht). Du musst lediglich ein _GraphicsClear($h_Backbuffer, 0) VOR SetClipRect einfügen, das setzt alle Pixel der Grafik auf die Farbe 0x00000000, also schwarz und komplett transparent.

  • Sorry, ich hab deinen Thread irgendwie vergessen... ^^

    Macht nichts. Man kann ja nicht immer vor Ort sein. ^^

    Vielen Dank für die Hilfe. Jetzt weiß ich wenigstens auch, wie die Funktion funktioniert. :thumbup: