Pic reapeat als GUI Hintergrund (ala CSS bei HTML)

  • Hallo,
    jeder, der öfter mit CSS-Styles arbeitet, weiß, wie einfach es ist, dass sich ein kleines Bild über die ganze HTML Seite wiederholt.
    Dazu reicht ja der Style "background: url(pfad zum bild) -repeat;"

    Ich möchte jetzt eine GUI erstellen, die in ihrer Größe verändert werden kann. Dabei soll dieses kleine Bild immer wiederholt werden. Miranda kann das z.B. auch.

    Jemand eine Idee, wie ich das am besten hinbekomme?

    Beispielbild:
    [Blockierte Grafik: http://img5.imagebanana.com/img/9r3toy90/stripes.png]

  • Hab mal eine kleine Funktion mit GDI+ gebastelt. :)

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

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

    _RepeatPicture(@ScriptDir & "\stripes.png", @ScriptDir & "\Test.png", 400, 400)

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

    Func _RepeatPicture($sPath_Src, $sPath_Dst, $iWidth_Dst, $iHeight_Dst)
    ; Author: name22(http://www.autoit.de)

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

    _GDIPlus_Startup()

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

    $hImage_Src = _GDIPlus_ImageLoadFromFile($sPath_Src)
    $hTexture_Src = _GDIPlus_TextureCreate($hImage_Src)

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

    $hGraphic_Tmp = _GDIPlus_GraphicsCreateFromHWND(WinGetHandle(AutoItWinGetTitle()))
    $hBitmap_Dst = _GDIPlus_BitmapCreateFromGraphics($iWidth_Dst, $iHeight_Dst, $hGraphic_Tmp)
    $hGraphic_Dst = _GDIPlus_ImageGetGraphicsContext($hBitmap_Dst)

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

    _GDIPlus_GraphicsFillRect($hGraphic_Dst, 0, 0, $iWidth_Dst, $iHeight_Dst, $hTexture_Src)
    _GDIPlus_ImageSaveToFile($hBitmap_Dst, $sPath_Dst)

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

    _GDIPlus_GraphicsDispose($hGraphic_Tmp)
    _GDIPlus_GraphicsDispose($hGraphic_Dst)
    _GDIPlus_BitmapDispose($hBitmap_Dst)
    _GDIPlus_ImageDispose($hImage_Src)
    _GDIPlus_BrushDispose($hTexture_Src)
    _GDIPlus_Shutdown()
    EndFunc

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_TextureCreate
    ; Description ...: Creates a TextureBrush object based on an image and a wrap mode
    ; Syntax.........: _GDIPlus_TextureCreate($hImage[, $iWrapMode = 0])
    ; Parameters ....: $hImage - Pointer to an Image object
    ; $iWrapMode - Wrap mode that specifies how repeated copies of an image are used to tile an area when it is
    ; +painted with the texture brush:
    ; |0 - Tiling without flipping
    ; |1 - Tiles are flipped horizontally as you move from one tile to the next in a row
    ; |2 - Tiles are flipped vertically as you move from one tile to the next in a column
    ; |3 - Tiles are flipped horizontally as you move along a row and flipped vertically as you move along a column
    ; |4 - No tiling takes place
    ; Return values .: Success - Pointer to a new TextureBrush object
    ; Failure - 0 and either:
    ; |@error and @extended are set if DllCall failed
    ; |$GDIP_STATUS contains a non zero value specifying the error code
    ; Remarks .......: The size of the brush defaults to the size of the image, so the entire image is used by the brush
    ; After you are done with the object, call _GDIPlus_BrushDispose to release the object resources
    ; Related .......: _GDIPlus_BrushDispose
    ; Link ..........; @@MsdnLink@@ GdipCreateTexture
    ; Example .......; No
    ; ===============================================================================================================================
    Func _GDIPlus_TextureCreate($hImage, $iWrapMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateTexture", "hwnd", $hImage, "int", $iWrapMode, "int*", 0)

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

    If @error Then Return SetError(@error, @extended, 0)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[3]
    EndFunc ;==>_GDIPlus_TextureCreate

    [/autoit]
  • Ok, das erstellt mir ein Bild mit der bestimmten Größe, aber könnte ich nicht das direkt in einem Control erzeugen, ohne diesen Umweg?

  • Ok, habe jetzt erstmal deine Methode eingebaut. Allerdings kann ich das glaube ich auch schon wieder vergessen^^
    Ich habe eine GUI mit extrem vielen Controls drauf, die alle bestimmte Daten angeben und jede Sekunde aktualisiert werden. Wenn ich jetzt für die ganze GUI (ca. 800x500px) den Hintergrund setze, dauert das Refreshen der Labels extrem lange... Mein PC wird doch wohl nicht zu schlecht dafür sein?

  • So?

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    Global $hGCPRGraphics, $hGCPRBitmap, $sImage="test.png"
    $hGUI=GUICreate("")
    GUISetState()
    GUICtrlPicRepeat($hGUI, $sImage, 20, 20, 300, 300)
    While True
    Switch GUIGetMsg()
    Case -3
    Exit
    EndSwitch
    WEnd
    Func GUICtrlPicRepeat($hWnd, $sPic, $iX, $iY, $iWidth, $iHeight)
    Local $hImage, $iImageWidth, $iImageHeight, $hBuffer, $aPos
    If $hGCPRGraphics<>"" Then
    _GDIPlus_GraphicsDispose($hGCPRGraphics)
    _GDIPlus_BitmapDispose($hGCPRBitmap)
    _GDIPlus_Shutdown()
    GUIRegisterMsg(0x000F, "")
    OnAutoItExitUnregister("GCPRShutdown")
    EndIf
    _GDIPlus_Startup()
    $hGCPRGraphics=_GDIPlus_GraphicsCreateFromHWND($hWnd)
    $aPos=WinGetPos($hWnd)
    $hGCPRBitmap=_GDIPlus_BitmapCreateFromGraphics($aPos[2], $aPos[3], $hGCPRGraphics)
    $hBuffer=_GDIPlus_ImageGetGraphicsContext($hGCPRBitmap)
    $hImage=_GDIPlus_ImageLoadFromFile($sPic)
    $iImageWidth=_GDIPlus_ImageGetWidth($hImage)
    $iImageHeight=_GDIPlus_ImageGetHeight($hImage)
    For $i=$iX to $iWidth Step $iImageWidth
    For $n=$iY to $iHeight Step $iImageHeight
    _GDIPlus_GraphicsDrawImage($hBuffer, $hImage, $i, $n)
    Next
    Next
    _GDIPlus_GraphicsDrawImage($hGCPRGraphics, $hGCPRBitmap, 0, 0)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hBuffer)
    GUIRegisterMsg(0x000F, "GCPRReDraw")
    OnAutoItExitRegister("GCPRShutdown")
    EndFunc
    Func GCPRReDraw()
    _GDIPlus_GraphicsDrawImage($hGCPRGraphics, $hGCPRBitmap, 0, 0)
    EndFunc
    Func GCPRShutdown()
    _GDIPlus_BitmapDispose($hGCPRBitmap)
    _GDIPlus_GraphicsDispose($hGCPRGraphics)
    _GDIPlus_Shutdown()
    EndFunc

    [/autoit]
  • Mit der Funktion ist es so, dass alle Controls ständig überdeckt werden (bis auf einige wenige).

  • Das Bild wird doch immer neu gezeichnet oder? Habe deine Funktion direkt nach dem Erstellen der GUI aufgerufen, dann folgen erst die Controls. Wenn ich das redrawen weglasse, und stattdessen nur 1x aufrufe, kommt gar kein Bild.

    • Offizieller Beitrag

    Heyho,

    Nicht besonders sauber und schnell, aber es funktioniert ;) Allerdings nicht als png, nur jpg, gif oder bmp:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    $hWnd = GUICreate("")
    GuiSetBKPicRepeat($hWnd, @ScriptDir&"\stripes.jpg")
    GUICtrlCreateButton("TEST",0,0)

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

    GUISetState()
    While GUIGetMsg() <> -3
    WEnd

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

    Func GuiSetBKPicRepeat($hWnd, $sFile)
    $aPos = WinGetPos($hWnd)
    _GDIPlus_Startup()
    $hBit = _GDIPlus_BitmapCreateFromFile($sFile)
    $iH = _GDIPlus_ImageGetHeight($hBit)
    $iW = _GDIPlus_ImageGetWidth($hBit)
    _GDIPlus_BitmapDispose($hBit)
    For $i = 0 To $aPos[2] Step $iW
    For $j = 0 To $aPos[3] Step $iH
    GUICtrlCreatePic($sFile,$i,$j,$iW,$iH)
    GUICtrlSetState(-1,$GUI_DISABLE)
    Next
    Next
    EndFunc

    [/autoit]

    Gruß
    Spider

  • Wow, das klappt sogar so ganz gut. Ist zwar leicht langsamer, aber erträglich!
    Jetzt wäre das gelöst, jetzt stehe ich vor neuen Problemen:
    1. Meine ListView hat noch eine bestimmte Farbe als Hintergrund. Ich weiß, dass man dieser auch ein Bild zuweisen kann als BG, aber das passt dann nicht zum übrigen der GUI. Kann ich der ListView einen transparenten BG geben?
    2. Ich habe ein Graphikfeld (durch HWND von Pic Control), in das Bilder per GDI+ geladen werden. Wenn gerade kein Bild geladen ist, soll halt der BG der GUI durchscheinen, stattdessen ist das Feld schwarz (benutze _GDIPlus_GraphicsClear). Wie bekomme ich das wieder transparent?
    3. Ich benutze außerdem Gruppen. Da wo der Text der Gruppe steht, ist ein e Hintergrundfarbe (damit der Balken, der um die Gruppe geht, verdeckt wird, da wo der Text ist). Diese Hintergrundfarbe sorgt dafür, dass da das Bild nicht durchkommt^^ Wenn ich der Group die Transparente BG Farbe gebe, geht der Gruppenstrich (balken) durch den Text durch..

    Diese 3 für mich unlösbaren Probleme habe ich...

  • Zu 2) _GDIPlus_GraphicsClear(0x00FFFFFF) (nur das 0x00 am Anfang ist wichtig, das FFFFFF ist egal)
    Zu 1 und 3) Versuch mal GUICtrlSetBkColor($CTRLID, -2) bin mir aber nicht sicher, ob das klappt.

  • Zu 2: Das klappt nicht =(
    Zu 1 und 3: Klappt nicht. Bei 1 hab ich das schon getestet, bei 3 hab ich ja schon geschrieben, was dann passiert =)

  • Poste mal dein GUI Code, denn ich habe eine Idee, wie du ein GDI+ Bild im Hintergrund haben kannst, ohne das die GUI Controls langsam aufgebaut werden.

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Naja, wenn ich den poste muss ich wieder fürchten, dass der Thread geschlossen wird. Geht nicht auch eine Sample GUI?

  • Habe mal eine BeispielGUI gemacht. Weiß jemand, wie man die ListView transparent (Header ist egal) und die Group vernünftig hinbekommt?

    Spoiler anzeigen
    [autoit]

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

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

    _GDIPlus_Startup()

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

    Dim $vGUIWidth = 400, $vGUIHeight = 400

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

    $hGUI = GUICreate("", $vGUIWidth, $vGUIHeight)
    GuiSetBKPicRepeat($hGUI, "stripes.jpg")

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

    GUICtrlCreateListView("col1|col2", 10, 10, 200, 200)

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

    _SetXPStyle(0)
    GUICtrlCreateGroup("Gruppe1", 220, 10, 160, 150)
    GUICtrlSetColor(-1, 0xffffff)
    GUICtrlSetBkColor(-1, -2);...
    _SetXPStyle(1)

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

    GUISetState()

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

    Do
    Until GUIGetMsg() = -3

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

    Func _SetXPStyle($b_Set = 1); 0 = deactivate, 1 = activate
    DllCall("uxtheme.dll", "none", "SetThemeAppProperties", "int", $b_Set * 7)
    EndFunc

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

    Func GuiSetBKPicRepeat($hWnd, $sFile)
    $hBit = _GDIPlus_BitmapCreateFromFile($sFile)
    $iH = _GDIPlus_ImageGetHeight($hBit)
    $iW = _GDIPlus_ImageGetWidth($hBit)
    _GDIPlus_BitmapDispose($hBit)

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

    For $i = 0 To $vGUIWidth Step $iW
    For $j = 0 To $vGUIHeight Step $iH
    GUICtrlCreatePic($sFile,$i,$j,$iW,$iH)
    GUICtrlSetState(-1,$GUI_DISABLE)
    Next
    Next
    EndFunc

    [/autoit]


    Das kleine Bild aus GtaSpider's Post ist zu nehmen.

    UEZ: Was war denn das für eine Idee, die du hattest?

  • Probiere es mal damit:

    Spoiler anzeigen
    [autoit]


    #include <GDIPlus.au3>
    #include <GuiListView.au3>
    #include <ListViewConstants.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>

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

    _GDIPlus_Startup()

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

    Global $vGUIWidth = 400, $vGUIHeight = 400
    Global $hGraphic, $hBitmap, $hBackbuffer, $hImage, $hTexture

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

    Global $hGUI = GUICreate("", $vGUIWidth, $vGUIHeight, -1, -1)
    Global $hGUI2 = GUICreate("", $vGUIWidth, $vGUIHeight, 0, 0, $WS_POPUP, $WS_EX_LAYERED + $WS_EX_MDICHILD, $hGUI)
    GUISetBkColor(0xABCDEF, $hGUI2)

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

    Global $lv = GUICtrlCreateListView("col1|col2", 10, 10, 200, 200, $LVS_NOCOLUMNHEADER)
    GUICtrlSetBkColor(-1, 0xABCDEF)
    GUICtrlSetColor(-1, 0x004000)

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

    Global $b = GUICtrlCreateButton("Exit", 10, $vGUIHeight - 50)
    _SetXPStyle(0)
    Global $g = GUICtrlCreateGroup("Gruppe1", 220, 10, 160, 150)
    GUICtrlSetColor(-1, 0x000040)
    GUICtrlSetBkColor(-1, -2);...
    _SetXPStyle(1)

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

    GUISetState(@SW_SHOW, $hGUI2)
    GUISetState(@SW_SHOW, $hGUI)

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

    _WinAPI_SetLayeredWindowAttributes($hGUI2, 0xABCDEF)

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

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($vGUIWidth, $vGUIHeight, $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\test.jpg")
    $hTexture = _GDIPlus_TextureCreate($hImage)

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

    _GDIPlus_GraphicsFillRect($hBackbuffer, 0, 0,$vGUIWidth, $vGUIHeight, $hTexture)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $vGUIWidth, $vGUIHeight)

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

    GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")

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

    For $i = 0 To 50
    _GUICtrlListView_AddItem($lv, Random(0x111111, 0xFFFFFF, 1))
    Next

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

    Do
    Until GUIGetMsg() = -3

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

    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_BrushDispose($hTexture)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    GUIDelete($hGUI2)
    GUIDelete($hGUI)
    Exit

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

    Func WM_ERASEBKGND($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $vGUIWidth, $vGUIHeight)
    Return 1
    EndFunc ;==>WM_PAINT

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

    Func _SetXPStyle($b_Set = 1); 0 = deactivate, 1 = activate
    DllCall("uxtheme.dll", "none", "SetThemeAppProperties", "int", $b_Set * 7)
    EndFunc

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

    Func _GDIPlus_TextureCreate($hImage, $iWrapMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateTexture", "hwnd", $hImage, "int", $iWrapMode, "int*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[3]
    EndFunc ;==>_GDIPlus_TextureCreate

    [/autoit]

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (27. Januar 2011 um 00:00)

  • Ok, der Ansatz sieht gut aus. Ob dieser besser ist als dutzende kleine Pic Controls (siehe GtaSpider) könnte ich zwar jetzt testen, bringt mir aber erstmal nicht viel. Denn Fakt ist, wenn ich die Listview nicht transparent bekomme, und die Gruppenbezeichnung nicht hinbekomme (ok, diese könnte ich notfalls per GDI+ zeichnen), kann ich die ganze Geschichte mit dem Hintergrund vergessen...

    Also hat jemand eine Idee, wie ich die Listview transparent bekomme?^^ (wie gesagt, Header ist unwichtig, da der in meinem Programm eh nicht vorhanden ist)

    Gute Nacht.
    NoName

  • Hi,
    schaut ja schonmal gut aus. Allerdings stört es mich etwas, dass dafür 2 Fenster eingesetzt werden. Kann man das auch alles auf einem machen?

    Habe jetzt mal ein bisschen rumprobiert, aber entweder die Controls sind nicht sichtbar, oder die das ganze Fenster ist da transparent, wo die ListView ist...
    MfG