GDI+ CloneArea Problem

  • Hallo,

    Gegeben sei dieser Code:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>

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

    _GDIPlus_Startup()

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

    $hGUIMinimap = GUICreate("", 400, 200)
    $hGUIMinimap1 = GUICtrlCreatePic("", 5, 5, 190, 190)
    $hGUIMinimap2 = GUICtrlCreatePic("", 205, 5, 190, 190)

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

    GUISetState()
    _FillGraphics()

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

    While 1
    Switch GUIGetMsg()
    Case - 3
    Exit
    EndSwitch
    Sleep(1)
    WEnd

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

    Func _FillGraphics()
    $hBitmap = _GDIPlus_ImageLoadFromFile("auge.jpg")
    $hBitmap2 = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, 190, 190)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap2)
    $hNewBitmapHandle = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap2)
    _SetBitmapToCtrl($hGUIMinimap1, $hNewBitmapHandle)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($hNewBitmapHandle)

    $hBitmap = _GDIPlus_ImageLoadFromFile("auge.jpg")
    $hBitmap2 = _GDIPlus_BitmapCloneArea($hBitmap, -1, 0, 190, 190)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap2)
    $hNewBitmapHandle = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap2)
    _SetBitmapToCtrl($hGUIMinimap2, $hNewBitmapHandle)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($hNewBitmapHandle)
    EndFunc ;==>_PrepareBitmap

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

    Func _SetBitmapToCtrl($vCtrlID, $hBitmap)
    Local $hWnd = GUICtrlGetHandle($vCtrlID)
    If $hWnd = 0 Then Return SetError(1, 0, 0)

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

    Local $vOldStyle = _WinAPI_GetWindowLong($hWnd, -16)
    _WinAPI_SetWindowLong($hWnd, -16, BitOR($vOldStyle, 0xE))

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

    Local $vOldBmp = _SendMessage($hWnd, 0x0172, 0, $hBitmap)
    If $vOldBmp <> 0 Then _WinAPI_DeleteObject($vOldBmp)
    EndFunc ;==>_SetBitmapToCtrl

    [/autoit]

    Dazu wird dieses Bild benötigt (im selben Ordner wie das Script).
    [Blockierte Grafik: http://img5.imagebanana.com/img/2fu4zdkz/auge.jpg]

    Nun zum Problem:
    Es sollten 2 Bilder im Programm erscheinen, jeweils ein geklonter Bereich aus dem Ursprungsbild, aber die Funktion zum Klonen des Bereiches funktioniert nur, wenn man nicht über das Bild in irgendeine Richtung hinaus klont. Das Bild muss aber immer die Breite von 190 und die Höhe von 190 Pixeln haben. Früher habe ich die Funktion DrawImageRectRect benutzt, die aber beim Wechsel des Bildes des öfteren geflackert hat. Der Funktion ist es egal, wenn man über das Bild hinausschießt, sie hat sich einfach eine weiße Fläsche dahin gedacht, CloneArea aber liefert einen Fehler in Zeile 31, aufgrund der -1. Kann ich CloneArea irgendwie umgehen?

    Einmal editiert, zuletzt von NoName (4. September 2009 um 18:11)

  • Ja, ich will ja dass es auch iwie klappt, wenn er bei -1 anfängt zu klonen^^ Oder allgemein übers Bild hinaus.

  • Hat mir leider nicht geholfen. Die einfachste Lösung wäre wohl DrawImageRectRect, aber die FUnktion hat bei mir immer geflackert, da ich vorher immer mit DrawImageRect einen schwarzen Hintergrund gemalt habe, falls beim clonen des Bildes über den Rand gegangen wurde. Aber durch das schwarzmalen vorher hat das so geflackert, denn ohne das flackerte es nicht so =(

  • Kannst du bitte mir nochmals erklären, was du genau machen willst!

    Ich dachte, dass du ein Bild laden und es anschließend auf irgendeine Seite clonen willst! ?(

    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Also, man hat in einem Spiel seinen Charakter, ahand der X und Y Koordinaten des Chars kann man diesen auf einer Minimap anzeigen. Die Map ist aber 3000x768 Pixel groß, ich will allerdings nur eine Minimap 190x190Pixel anzeigen lassen. Der Char wird durch einen Punkt immer in der Mitte angezeigt. Man stelle sich jetzt vor, der Char würde ganz links auf der Map stehen, sodass, wenn ich die Minimap zeichnen würde, ich im - Bereich anfangen müsste zu klonen, sonst müsste ich den Punkt des Chars verändern, was aber zu umständlich wäre. Und in solch einer Situation, wenn man an einen Grenzwert der Karte kommt, liefert halt CloneArea den Fehler, weil er da nichts zum klonen hat an gewissen Stellen. Mit DrawImageRectRect ging das, aber flackerte so extrem, deshalb suche ich eine Alternative.

    Ich hoffe ich konnte das jetzt gut erklären.

    @Mods: Wenn ihr an einen Bot oder ähnliches denkt, habt ihr falsch gedacht =)

    Achso: Mein Beispielscript sollte eigentlich nur zeigen, dass CloneArea nicht funktioniert, wenn z.B. bei -1 angefangen wird zu klonen.

    Edit: Dank dieses Beispiels, habe ich es hinbekommen, dass das Bild nicht mehr flackert, wenn es erneuert wird, und ich kann DrawImageRectRect nutzen, womit ich beim klonen keine Probleme mehr habe =)
    Dieses Script hat mir geholfen (hat Malkey aus dem englischen Forum gepostet):

    Spoiler anzeigen
    [autoit]

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

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

    Opt("GUIOnEventMode", 1) ;0=disabled, 1=OnEvent mode enabled

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

    Global $ApW = 400, $ApH = 200
    Global $Button[1]

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

    $hGui = GUICreate("GDIPlus Graphics on Picture Control - OnEvent Mode", $ApW + 40, $ApH + 40)
    GUISetOnEvent(-3, "_Quit")
    GUISetBkColor(0x303030, $hGui)

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

    $Pic = GUICtrlCreatePic("", 20, 20, 190, 190)
    GUICtrlSetBkColor(-1, 0xFFFF00)
    GUICtrlSetState(-1, $GUI_DISABLE)
    $Pic1 = GUICtrlCreatePic("", 230, 20, 190, 190)
    GUICtrlSetBkColor(-1, 0xFFFF00)
    GUICtrlSetState(-1, $GUI_DISABLE)

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

    PicSetGraphics($Pic, -160, -40)
    PicSetGraphics2($Pic1, 20, 50)

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

    While 1
    Sleep(10)
    WEnd

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

    Func PicSetGraphics($cID, $iW, $iH)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local $hWnd, $hBitmap, $hImage, $hGraphic, $hBrush, $hBrush1, $hbmp, $aBmp
    $hWnd = GUICtrlGetHandle($cID)
    _GDIPlus_Startup()
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hWnd) ; added
    $hImage = _GDIPlus_BitmapCreateFromGraphics(190, 190, $hGraphicGUI);added
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage); original
    _GDIPlus_GraphicsClear($hGraphic, 0xFF000000) ;added - Instead of bitmap colour, This adds the colour.
    GUISetState(@SW_SHOW, $hGui)

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

    ;-----> All Graphics Here
    $hBitmap = _GDIPlus_ImageLoadFromFile("auge.jpg")
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, $iW, $iH, 640, 512)
    ; -----> End of all Graphics

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

    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
    _WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))

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

    ; Save Graphics on picture control
    ;_GDIPlus_ImageSaveToFile($hImage, @DesktopDir & "\TestWrite1.png")
    ;ShellExecute(@DesktopDir & "\TestWrite1.png")

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

    If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
    _WinAPI_DeleteObject($hbmp)
    _WinAPI_DeleteObject($hImage)
    _GDIPlus_BrushDispose($hBrush1)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hGraphicGUI)

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

    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()
    EndFunc ;==>PicSetGraphics

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

    Func PicSetGraphics2($cID, $iW, $iH)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local $hWnd, $hBitmap, $hImage, $hGraphic, $hBrush, $hBrush1, $hbmp, $aBmp
    $hWnd = GUICtrlGetHandle($cID)
    _GDIPlus_Startup()
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hWnd) ; added
    $hImage = _GDIPlus_BitmapCreateFromGraphics(190, 190, $hGraphicGUI);added
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage); original
    _GDIPlus_GraphicsClear($hGraphic, 0xFF000000) ;added - Instead of bitmap colour, This adds the colour.
    GUISetState(@SW_SHOW, $hGui)

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

    ;-----> All Graphics Here
    $hBitmap = _GDIPlus_ImageLoadFromFile("auge.jpg")
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, $iW, $iH, 300, 300)
    ; -----> End of all Graphics

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

    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
    _WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))

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

    ; Save Graphics on picture control
    ;_GDIPlus_ImageSaveToFile($hImage, @DesktopDir & "\TestWrite1.png")
    ;ShellExecute(@DesktopDir & "\TestWrite1.png")

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

    If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
    _WinAPI_DeleteObject($hbmp)
    _WinAPI_DeleteObject($hImage)
    _GDIPlus_BrushDispose($hBrush1)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hGraphicGUI)

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

    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()
    EndFunc ;==>PicSetGraphics2

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

    Func _Quit()
    Exit
    EndFunc ;==>_Quit

    [/autoit]

    Ich habe mein Script jetzt so verändert mit diesen Funktionen zum laufen bekommen:

    Spoiler anzeigen
    [autoit]

    $hGUIMap = GUICtrlCreatePic("", 544, 25, 190, 190)
    $hWnd = GUICtrlGetHandle($hGUIMinimap)

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

    $hBitmap = _GDIPlus_ImageLoadFromFile("WorldMap.jpg")
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $hImage = _GDIPlus_BitmapCreateFromGraphics(190, 190, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)

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

    _GDIPlus_GraphicsClear($hGraphic, 0xFF000000)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hBitmap, x, y, 190, 190, 0, 0, 190, 190)
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF00FF00)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 90, 90, 10, 10, $hBrush)
    $hBitmap2 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $vCall = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", 0x0172, "int", 0, "int", $hBitmap2)
    ;_WinAPI_RedrawWindow($hGui, "", "", BitOR(0x0001, 0x0100, 0x0400))

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

    _GDIPlus_BrushDispose($hBrush)
    If $vCall[0] <> 0 Then _WinAPI_DeleteObject($vCall[0])
    _GDIPlus_GraphicsDispose($hGraphicGUI)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hImage)
    _WinAPI_DeleteObject($hBitmap2)
    _GDIPlus_BitmapDispose($hBitmap)

    [/autoit]

    Danke für die Hilfe =)

    3 Mal editiert, zuletzt von NoName (4. September 2009 um 18:17)