Graphicinhalt mit Farbe füllen

  • Hi Community,

    ich stehe vor einem neuen Problem. Ich zeiche eine Graphic und möchte anschließend die eingeschlossene Fläche einfärben.

    Die Ränder/Kanten einer Fläche sind mit GUICtrlSetGraphic($Graphic, $GUI_GR_LINE, X,Y) gezeichnet.
    [Blockierte Grafik: http://johannes-log.spacequadrat.de/Do_Not_Delete/_splitter.JPG] -> [Blockierte Grafik: http://johannes-log.spacequadrat.de/Do_Not_Delete/_splitter_3.jpg]

    Vielen Dank schonmal vorweg!

    Einmal editiert, zuletzt von Jautois (28. November 2009 um 13:58)

  • Soweit ich weiß, gibt es die Funktion des nachträglichen Füllens nicht!


    Mein Vorschlag: _GDIPlus_GraphicsFillClosedCurve

    Hier das Beispiel aus der Hilfe:

    [autoit]


    #include <GuiConstantsEx.au3>
    #include <GDIPlus.au3>
    Opt('MustDeclareVars', 1)
    _Main()
    Func _Main()
    Local $hGUI, $hWnd, $hGraphic, $aPoints[8][2]
    ; Create GUI
    $hGUI = GUICreate("GDI+", 400, 300)
    $hWnd = WinGetHandle("GDI+")
    GUISetState()
    ; Fill a cardinal spline
    _GDIPlus_Startup ()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hWnd)
    $aPoints[0][0] = 7
    $aPoints[1][0] = 50
    $aPoints[1][1] = 50
    $aPoints[2][0] = 100
    $aPoints[2][1] = 25
    $aPoints[3][0] = 200
    $aPoints[3][1] = 5
    $aPoints[4][0] = 250
    $aPoints[4][1] = 50
    $aPoints[5][0] = 300
    $aPoints[5][1] = 100
    $aPoints[6][0] = 350
    $aPoints[6][1] = 200
    $aPoints[7][0] = 250
    $aPoints[7][1] = 250
    _GDIPlus_GraphicsFillClosedCurve ($hGraphic, $aPoints)
    ; Loop until user exits
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    ; Clean up resources
    _GDIPlus_GraphicsDispose ($hGraphic)
    _GDIPlus_Shutdown ()
    EndFunc ;==>_Main

    [/autoit]

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Cool danke!

    Ich kann allerdings nicht abfragen, ob auf die Grafik geklickt wurde. Ich hatte es so (ausgehend von dem Beispiel):

    [autoit]


    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $hGraphic
    MsgBox(32,"Info","Grafik geklickt!")
    EndSwitch
    WEnd

    [/autoit]
  • Wieso nimmst du handle vom Fenster wenn GUICreate n handle returned?

  • Ich hab dir auch noch ein Beispiel, mit GDI32 ;)

    Spoiler anzeigen
    [autoit]

    #include<WinAPI.au3>
    #include"GDI.au3"

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

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

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

    Global $aPoints[8][2]
    $aPoints[0][0] = 7
    $aPoints[1][0] = 50
    $aPoints[1][1] = 50
    $aPoints[2][0] = 100
    $aPoints[2][1] = 25
    $aPoints[3][0] = 200
    $aPoints[3][1] = 5
    $aPoints[4][0] = 250
    $aPoints[4][1] = 50
    $aPoints[5][0] = 300
    $aPoints[5][1] = 100
    $aPoints[6][0] = 350
    $aPoints[6][1] = 200
    $aPoints[7][0] = 250
    $aPoints[7][1] = 250

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

    Global $htestRegion = _GDI_CreatePolyRgn($aPoints)
    Global $hFillBrush = _GDI_CreateSolidBrush(0xFF0000)

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

    Call("On" & "AutoItExitRegister", "OnAutoItExit")
    Func OnAutoItExit()
    _GDI_DeleteObject($htestRegion)
    _GDI_DeleteObject($hFillBrush)
    EndFunc

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

    #region - GUI Create
    Global $TestGUI = GUICreate('test')
    GUIRegisterMsg($WM_PAINT, '_WM_PAINT')
    GUISetState()
    #endregion

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

    #region - GUI SelectLoop
    While 1
    $msg = GUIGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
    Exit
    Case $msg = $GUI_EVENT_PRIMARYUP
    $aInfo = GUIGetCursorInfo()
    If _GDI_PtInRegion($htestRegion, $aInfo[0], $aInfo[1]) Then
    MsgBox(0, '', "In Region", 1)
    EndIf
    EndSelect
    WEnd
    #endregion

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

    Func _WM_PAINT($hWnd, $Msg, $wParam, $lParam)
    If $hWnd = $TestGUI Then
    $tPS = DllStructCreate($tagPAINTSTRUCT)
    $hDC = _GDI_BeginPaint($hWnd, DllStructGetPtr($tPS))
    If 0 <> _GDI_RectInRegion($htestRegion, DllStructGetPtr($tPS, 'rcPaint')) Then
    _GDI_FillRgn($hDC, $htestRegion, $hFillBrush)
    EndIf
    _GDI_EndPaint($hWnd, DllStructGetPtr($tPS))
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit]

    Du brauchst dafür die GDI UDFs

  • Das ist mal cool geht das auch mit Elypsen die man nicht mit GDI-Plus gemalt sind?
    Ich habe nähmlich ein Bild und das möchte ich als Button Benutzen und man soll nur Draufklicken können wenn man im Bereich des Buttons ist und nicht im 4-Eck

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Form1", 625, 443, 192, 124)
    $Pic1 = GUICtrlCreatePic ("6.gif",15,50,110,20)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Pic1
    MsgBox (0,"","Klick")
    EndSwitch
    WEnd

    [/autoit]

    Ich hab das bisher auch so wie cih gezeigt hab gemacht also mit color, aber dann muss der Hintergrund einfarbig sein :(

  • Jam00: Du kannst es auch so machen:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <WinAPI.au3>
    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Form1", 625, 443, 192, 124)

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

    $Pic1 = GUICtrlCreatePic (@MyDocumentsDir&"\Eigene Bilder\6.gif",15,50,110,20)

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

    GUISetState(@SW_SHOW)
    $Region = _WinAPI_CreateRoundRectRgn(0,0,110,20, 15, 15)
    _WinAPI_SetWindowRgn(GUICtrlGetHandle($Pic1), $Region)

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

    #EndRegion ### END Koda GUI section ###

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Pic1
    MsgBox (0,"","Klick")
    EndSwitch
    WEnd

    [/autoit]
  • @progandy
    Jo so kann man es auch machen, aber geht das auch irgendwie mit der GDI.au3? Gibts dazu eine Hilfedatei?


    Warum willst du es mit der GDI.au3 machen? Dann ersetze halt bei den beiden Befehlen _WinAPI_ mit _GDI_, das sind die gleichen Funktionen
    Eine Hlife gibt es nicht, nur die Funktionskommentare und MSDN, aber in einer Hilfedatei wäre auch nichts anderes drin. ;)

  • Du musst die Form eben über die $Region definieren ;)
    In der WinAPI sind Funktionen für CreateRectRgn und CreateRoundRectRgn drin, die GDI-UDFs haben zusätzlich noch _GDI_CreateEllipticRgn, _GDI_CreatePolyRgn, _GDI_CreateTriangleRgn

  • Könntest du mir noch ein kleines Beispiel zu der GDI.au3 machen? Ich weiß es nervt, aber ich habs noch cnith ganz gerallt

    Spoiler anzeigen
    [autoit]

    #include <GUIConstants.au3>
    #include <GDI.au3>

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

    #region - GUI Create
    GUICreate('test', 500, 400)
    $1 = GUICtrlCreateLabel("$1", 140, 10, 100, 100)
    GUICtrlSetBkColor(-1, 0xFF0000)
    $2 = GUICtrlCreateLabel("$2", 250, 10, 100, 100)
    GUICtrlSetBkColor(-1, 0xFF0000)
    $3 = GUICtrlCreateLabel("$3", 360, 10, 100, 100)
    GUICtrlSetBkColor(-1, 0xFF0000)
    $4 = GUICtrlCreateLabel("$4", 140, 140, 100, 100)
    GUICtrlSetBkColor(-1, 0xFF0000)
    $5 = GUICtrlCreateLabel("$5", 250, 140, 100, 100)
    GUICtrlSetBkColor(-1, 0xFF0000)
    GUISetState()

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

    $Region = _GDI_CreateRectRgn(15, 15, 70, 70)
    _GDI_SetWindowRgn(GUICtrlGetHandle($1), $Region)

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

    $Region = _GDI_CreateRoundRectRgn(15, 15, 70, 70, 20, 20)
    _GDI_SetWindowRgn(GUICtrlGetHandle($2), $Region)

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

    $Region = _GDI_CreateTriangleRgn(15, 15, 70, 70)
    _GDI_SetWindowRgn(GUICtrlGetHandle($3), $Region)

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

    $Region = _GDI_CreateEllipticRgn(15, 15, 70, 70)
    _GDI_SetWindowRgn(GUICtrlGetHandle($4), $Region)

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

    Local $aPoints[6][2] = [ [ 50, 10 ], [85, 33], [85, 66], [50, 90], [15, 66], [15, 33] ]
    $Region = _GDI_CreatePolyRgn($aPoints)
    _GDI_SetWindowRgn(GUICtrlGetHandle($5), $Region)

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

    #endregion

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

    #region - GUI SelectLoop
    While 1
    $msg = GUIGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
    Exit
    Case $msg = $1
    MsgBox(0, '', "$1")
    Case $msg = $2
    MsgBox(0, '', "$2")
    Case $msg = $3
    MsgBox(0, '', "$3")
    Case $msg = $4
    MsgBox(0, '', "$4")
    Case $msg = $5
    MsgBox(0, '', "$5")
    EndSelect
    WEnd
    #endregion

    [/autoit]


    Wenn man das Fenster minimiert wird irgendwe wieder das ganze Control-Rechteck bemalt, aber die Klicks werden trotzdem nur innerhalb der Region aufgenommen.

    @Jautois: Sieht gut aus ;)

  • Hier noch eine Version:

    Spoiler anzeigen
    [autoit]


    #include <GuiConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <Misc.au3>
    Opt('MustDeclareVars', 1)
    Opt("MouseCoordMode", 2)

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

    Global $hGUI, $hWnd, $hGraphic, $hBrush, $aPoints[8][2]
    Global $msg, $aPos

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

    ; Create GUI
    $hWnd = GUICreate("GDI+ Intersection with Polygon by UEZ (Kudos to Malkey!)", 400, 400)
    GUISetState()

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

    ; Fill a cardinal spline
    _GDIPlus_Startup()
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF0000FF)

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

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    _GDIPlus_GraphicsClear($hGraphic)

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

    $aPoints[0][0] = 5; Number of sides of Polygon
    $aPoints[1][0] = 100
    $aPoints[1][1] = 100
    $aPoints[2][0] = 300
    $aPoints[2][1] = 150
    $aPoints[3][0] = 300
    $aPoints[3][1] = 200
    $aPoints[4][0] = 150
    $aPoints[4][1] = 300
    $aPoints[5][0] = 70
    $aPoints[5][1] = 200
    $aPoints[6][0] = 100;Last point same as 1st point. Polygon is closed
    $aPoints[6][1] = 100

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

    _GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints, $hBrush)

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

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    ; Clean up resources
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_Shutdown()
    Exit
    Case $GUI_EVENT_PRIMARYUP
    $aPos = MouseGetPos()
    If _PointInPoly($aPos[0], $aPos[1], $aPoints) Then
    _GDIPlus_BrushSetSolidColor($hBrush, 0xFF000000 + Random(0x400000, 0xFFFFFF, 1))
    _GDIPlus_GraphicsFillPolygon($hGraphic, $aPoints, $hBrush)
    EndIf
    EndSwitch
    WEnd

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

    Func _GDIPlus_BrushSetSolidColor($hBrush, $iARGB = 0xFF000000)
    Local $aResult
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetSolidFillColor", "hwnd", $hBrush, "int", $iARGB)
    If @error Then Return SetError(@error, @extended, 0)
    Return SetError($aResult[0], 0, $aResult[0] = 0)
    EndFunc ;==>_GDIPlus_BrushSetSolidColor

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

    ; ($x, $y) - x, y position of the point to check
    ; $aPoints - An array of x,y values representing the nodes of a polygon.
    ; Finds the individual x values of the interestion of the individual sides of the polygon with the
    ; line y = $y (parallel with x-axis). If the number of x values found greater than $x is even, then
    ; the ($x, $y) point is outside the closed polygon. Plus, if $y is beyond the y values of the end
    ; points of individual sides of the polygon, the y = $y line will not interest with that side and will
    ; not be counted. Returns equivalent of, even number of intersections false, and, odd true(inside polygon).
    ; Requires Iif()function
    Func _PointInPoly($x, $y, $aPoints)
    Local $bEvenNum = False, $xOnLine, $yMin, $yMax
    For $i = 1 To $aPoints[0][0]
    $yMin = _Iif($aPoints[$i + 1][1] < $aPoints[$i][1], $aPoints[$i + 1][1], $aPoints[$i][1])
    $yMax = _Iif($aPoints[$i + 1][1] > $aPoints[$i][1], $aPoints[$i + 1][1], $aPoints[$i][1])
    $xOnLine = -($y * $aPoints[$i + 1][0] - $y * $aPoints[$i][0] - $aPoints[$i][1] * $aPoints[$i + 1][0] + _
    $aPoints[$i][0] * $aPoints[$i + 1][1]) / (-$aPoints[$i + 1][1] + $aPoints[$i][1])
    If ($x < $xOnLine) And ($y > $yMin) And ($y <= $yMax) Then $bEvenNum = Not $bEvenNum
    Next
    Return $bEvenNum
    EndFunc ;==>_PointInPoly

    [/autoit]

    Danke an Malkey für die Funktion _PointInPoly() :thumbup:


    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Hier noch eine GDI32 Funktion: Flood Fill (Danke an Zedna für den ursprünglichen Code ) gemixt mit GDI+ :whistling: :

    Spoiler anzeigen
    [autoit]


    ;thanks to Zedna for the original code -> http://www.autoitscript.com/forum/index.ph…ew=findpost&p=3
    #include <GDIplus.au3>
    #include <GUIConstantsEx.au3>
    #Include <Misc.au3>

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

    Opt("GUIOnEventMode", 1)
    Opt("MouseCoordMode",2)

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

    Global $dll = DllOpen("user32.dll")

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

    _GDIPlus_Startup()
    Global $bitmap_from_file = _GDIPlus_BitmapCreateFromFile(@ScriptDir & '\South_America_Map.GIF')

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

    Global $width = _GDIPlus_ImageGetWidth ($bitmap_from_file)
    Global $height = _GDIPlus_ImageGetHeight ($bitmap_from_file)

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

    Global $hwnd = GUICreate("GDI32: Flood Fill Example", $width, $height)

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

    GUISetOnEvent(-3, "Close")
    GUISetState()

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

    Global $hDC = _WinAPI_GetDC($hWnd)
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)

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

    _GDIPlus_GraphicsDrawImageRect($hGraphics, $bitmap_from_file, 0, 0, $width, $height)

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

    $hBrush = DllCall("gdi32.dll", "long", "CreateSolidBrush", "int", 0xFF5050) ; fill color BGR
    $obj_orig = DLLCall("gdi32.dll", "int", "SelectObject", "int", $hDC, "int", $hBrush[0])

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

    While Sleep(50)

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

    If _IsPressed("01") And WinActive($hWnd) Then
    $mp = MouseGetPos()
    DllCall("gdi32.dll", "int", "FloodFill", "int", $hDC, "int", $mp[0], "int", $mp[1], "int", 0x00) ; border color
    EndIf
    WEnd

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

    Func Close()
    DllClose($dll)
    DLLCall("gdi32.dll" ,"int", "SelectObject", "hwnd", $hwnd, "int", $obj_orig[0])
    DLLCall("gdi32.dll","int","DeleteObject","int",$hBrush[0])
    _WinAPI_ReleaseDC($hWnd, $hDC)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]

    Am besten die Zip Datei benutzen, da dort auch die Grafik ist, um die Flächen zu füllen (lmt füllt die Fläche)!

    Gruß,
    UEZ