Jump to content

Recommended Posts

Posted

Hi,

 

I'm playing with GDIPlus drawing for few days and I can't find a way to optimize my script. In the code below, you'll see 50 frames created by GDIPlus functions. You can move them separately and when the drag is initiate, all the graphic is clear and every frames are redrawn. But it's sloooow.

Could you help me ?

Thanks for your time.

P.S : You will need the attached .jpg

 

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



AutoItSetOption("MouseCoordMode", 2)

;Register callback
$hKey_Proc = DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")
$hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
$hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_MOUSE_LL, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)

Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"

Global $currentEvent[2]
Global $iLBUTTONDOWN = 0
Global $iRBUTTONDOWN = 0
Global $iMBUTTONDOWN = 0
Global $LRClickStatus = 0
Global $RLClickStatus = 0
Global $LRDrag = 0
Global $RLDrag = 0
Global $LMDrag = 0
Global $RMDrag = 0
Global $doubleClickTime = 400
Global $tPoint


Local Const $width = Int(@DesktopWidth * 0.8), $height = Int(@DesktopHeight * 0.8)

Global $max_width = 1900
Global $max_height = 1000


; Initialize GDI+
_GDIPlus_Startup()

Local $GUI_title = "GDI+"
Global $hGUI = GUICreate($GUI_title, $width, $height, -1, -1, BitOR($GUI_SS_DEFAULT_GUI,$WS_THICKFRAME,$WS_TABSTOP))
$aggrandissement = GUICtrlCreateButton("+", 10, 10, 20)
$diminution = GUICtrlCreateButton("-", 40, 10, 20)
GUISetState()



; main graphic and buffer
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($max_width, $max_height, $hGraphics)
Global $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, 2)


Global $hBitmap_switch = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\OS6250-24M.jpg")
Global $iHeight_switch = _GDIPlus_ImageGetHeight($hBitmap_switch)


; exclude controls from GDI+ graphic region
Local $hRegion = _GDIPlus_RegionCreateFromRect(0, 0, $width, $height)
$aRect = ControlGetPos("", "", $aggrandissement)
_GDIPlus_RegionCombineRect($hRegion, $aRect[0], $aRect[1], $aRect[2], $aRect[3], 3)
$aRect = ControlGetPos("", "", $diminution)
_GDIPlus_RegionCombineRect($hRegion, $aRect[0], $aRect[1], $aRect[2], $aRect[3], 3)
_GDIPlus_GraphicsSetClipRegion($hGraphics, $hRegion)
_GDIPlus_RegionDispose($hRegion)


; Text format
Global $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000)
Global $hFormat = _GDIPlus_StringFormatCreate()
_GDIPlus_StringFormatSetAlign($hFormat, 1)
Global $hFamily = _GDIPlus_FontFamilyCreate("Arial")
Global $hFont = _GDIPlus_FontCreate($hFamily, 10, 2)

; for the frames drawing
Global $hPen = _GDIPlus_PenCreate(0xFF000000, 2)
Global $hBrush_cadre_titre = _GDIPlus_BrushCreateSolid(0x55FF0000)

Global $frame_width = 200
Global $frame_height = 200


Global $shift_X, $shift_Y
Global $move_inprogress = False
Global $index_stack
Global $iScale = 1


; creating array
Global $array[51][4]
$array[0][0] = 50

Local $startx = 50
Local $starty = 50
Local $guipos = WinGetPos($hGUI)
Local $intervalle_x = $guipos[2] / 10 ; width
Local $intervalle_y = $guipos[3] / 7 ; height

For $i = 1 To $array[0][0]

    ; auto positionning
    If Mod($i, 10) = 0 Then
        $x = $startx
        $y = $array[$i - 1][1] + $intervalle_y
    Else
        If $i - 1 = 0 Then ; premier passage
            $x = $startx
            $y = $starty
        Else
            $x = $array[$i - 1][0] + $intervalle_x
            $y = $array[$i - 1][1]
        EndIf
    EndIf

    $array[$i][0] = $x
    $array[$i][1] = $y
    $array[$i][2] = "Hello world " & $i
    $array[$i][3] = "Bye world " & $i
Next


_DrawStack()


GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUIRegisterMsg($WM_SIZE, "WM_SIZE")

While 1
    $msg = GUIGetMsg()

    Switch $msg

        Case $GUI_EVENT_CLOSE
            _Exit()

        Case $GUI_EVENT_MAXIMIZE
            $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)

        Case $aggrandissement
            $iScale = $iScale + 0.2
            _DrawStack($iScale)

        Case $diminution
            $iScale = $iScale - 0.2
            _DrawStack($iScale)

    EndSwitch
WEnd


Func _DrawStack($scale = 1, $index_en_cours = -1, $new_x = 0, $new_y = 0)
    Local $x, $y, $titre, $info, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hauteur_cadre_titre

    _GDIPlus_GraphicsClear($hBackbuffer, 0xFFF0F0F0)

    For $i = 1 To $array[0][0]
        $x = $array[$i][0]
        $y = $array[$i][1]
        $titre = $array[$i][2]
        $info = $array[$i][3]
        $tmp_cadre_largeur = Int($frame_width * $scale)
        $tmp_cadre_hauteur = Int($frame_height * $scale)
        $hauteur_cadre_titre = Int(16 * $scale) ; 15 pixels de haut

        If $index_en_cours = $i Then ; le stack en cours de déplacement suit les mouvements de la souris, les autres ne bougent pas
            $x = $new_x
            $y = $new_y
        EndIf

        $hFont = _GDIPlus_FontCreate($hFamily, Int(10 * $scale), 2)

        Local $tLayout_titre = _GDIPlus_RectFCreate($x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre)
        _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $titre, $hFont, $tLayout_titre, $hFormat, $hBrush)

        Local $tLayout_info = _GDIPlus_RectFCreate($x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre)
        _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $info, $hFont, $tLayout_info, $hFormat, $hBrush)

        _GDIPlus_GraphicsDrawRect($hBackbuffer, $x, $y, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hPen) ; cadre
        _GDIPlus_GraphicsFillRect($hBackbuffer, $x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre, $hBrush_cadre_titre) ; titre
        _GDIPlus_GraphicsDrawRect($hBackbuffer, $x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre, $hPen) ; info

        _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hBitmap_switch, $x + 2, $y + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch
    Next

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0);, $max_width, $max_height) ; copy from backbuffer to visible graphic

EndFunc


Func _Mouse_Proc($nCode, $wParam, $lParam)
    Local $info, $mouseData, $time, $timeDiff

    If $nCode < 0 Then
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam)
        Return $ret[0]
    EndIf

    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
    $mouseData = DllStructGetData($info, 3)
    $time = DllStructGetData($info, 5)
    $timeDiff = $time - $currentEvent[1]

    Select
        Case $wParam = $WM_MOUSEMOVE
            ;Test for Drag in here

            If $currentEvent[0] <> "LDrag" Or $currentEvent[0] <> "LRDrag" Or $currentEvent[0] <> "LMDrag" Then

                If $iLBUTTONDOWN = 1 Then
                    $currentEvent[0] = "LDrag"

                    If $move_inprogress Then
                        $mouseX = MouseGetPos(0)
                        $mouseY = MouseGetPos(1)

                        _DrawStack($iScale, $index_stack, $mouseX - $shift_X, $mouseY - $shift_Y)

                        $array[$index_stack][0] = $mouseX - $shift_X
                        $array[$index_stack][1] = $mouseY - $shift_Y

                    EndIf

                    If $iRBUTTONDOWN = 1 Then
                        $currentEvent[0] = "LRDrag"
                        $LRDrag = 2
                    EndIf
                EndIf
            EndIf

            If $currentEvent[0] <> "RDrag" Or $currentEvent[0] <> "RMDrag" Or $currentEvent[0] <> "LRDrag" Then
                If $iRBUTTONDOWN = 1 Then
                    $currentEvent[0] = "RDrag"
                EndIf
            EndIf

            If $currentEvent[0] <> "MDrag" Then
                If $iMBUTTONDOWN = 1 Then
                    $currentEvent[0] = "MDrag"
                    $currentEvent[1] = $time
                EndIf
            EndIf

            If $iRBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "RMDrag" Then
                $RMDrag = 2
                $currentEvent[0] = "RMDrag"
                $currentEvent[1] = $time
            EndIf

            If $iLBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "LMDrag" Then
                $LMDrag = 2
                $currentEvent[0] = "LMDrag"
                $currentEvent[1] = $time
            EndIf


        Case $wParam = $WM_MOUSEWHEEL

            If _WinAPI_HiWord($mouseData) > 0 Then
                ;Wheel Up
                $currentEvent[0] = "WheelUp"
                $currentEvent[1] = $time
            Else
                ;Wheel Down
                $currentEvent[0] = "WheelDown"
                $currentEvent[1] = $time
            EndIf

        Case $wParam = $WM_LBUTTONDOWN
            $mouseX = MouseGetPos(0)
            $mouseY = MouseGetPos(1)

            For $i = 1 To $array[0][0]
                If  $mouseX > $array[$i][0] And $mouseX < $array[$i][0] + $frame_width * $iScale And _
                    $mouseY > $array[$i][1] And $mouseY < $array[$i][1] + $frame_height * $iScale Then

                    $shift_X = $mouseX - $array[$i][0]
                    $shift_Y = $mouseY - $array[$i][1]

                    ; ... we can move
                    $move_inprogress = True
                    $index_stack = $i
                EndIf
            Next


            ; Register Button Down, check for Right/Left
            If $currentEvent[0] = "RClick" Then
                $LRClickStatus = 1
            EndIf

            $iLBUTTONDOWN = 1

        Case $wParam = $WM_LBUTTONUP
            ;Update $iLBUTTONDOWN
            $iLBUTTONDOWN = 0

            ;Test for Right/Left Click
            If $RLClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RLClick"
                $currentEvent[1] = $time
            EndIf
            If $currentEvent[0] = "LClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LDClick"
                $currentEvent[1] = $time
            EndIf

            ;Test for Drops
            If $currentEvent[0] = "LDrag" Then
                $currentEvent[0] = "LDrop"
                $currentEvent[1] = $time

                ; si un déplacement était en cours, on indique que c'est terminé puisqu'on vient de relacher le bouton de la souris
                If $move_inprogress Then
                    $move_inprogress = False
                EndIf

            EndIf

            If $LRDrag = 2 And $iRBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf

            If $LMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $LMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "LClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $RLClickStatus = 0


        Case $wParam = $WM_RBUTTONDOWN
            ;Register Button Down
            If $currentEvent[0] = "LClick" Then
                $RLClickStatus = 1
            EndIf
            $iRBUTTONDOWN = 1

        Case $wParam = $WM_RBUTTONUP
            ;Test for Left, Right, and Right Doubleclick here
            ;Update $iRBUTTONDOWN
            $iRBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $LRClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LRClick"
                $currentEvent[1] = $time
            EndIf
            If $currentEvent[0] = "RClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "RDrag" Then
                $currentEvent[0] = "RDrop"
                $currentEvent[1] = $time
            EndIf

            If $LRDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf



            If $RMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "RClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $LRClickStatus = 0


        Case $wParam = $WM_MBUTTONDOWN
            ;Register Button Down
            $iMBUTTONDOWN = 1

        Case $wParam = $WM_MBUTTONUP
            ;Test for Middle Double Click here
            ;Update $iRBUTTONDOWN
            $iMBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $currentEvent[0] = "MClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "MDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "MDrag" Then
                $currentEvent[0] = "MDrop"
                $currentEvent[1] = $time
            EndIf

            If $LMDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LMDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf



            If $RMDrag = 2 And $iRBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set MClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "MClick"
                $currentEvent[1] = $time
            EndIf

    EndSelect

;~  If $currentEvent[0] <> "" Then ConsoleWrite("event:"&$currentEvent[0] & @CRLF)

    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc


Func WM_PAINT($hwnd, $iMsg, $wParam, $lParam)
    If $hwnd = $hGUI Then
        _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
        _WinAPI_RedrawWindow($hwnd, 0, 0, $RDW_VALIDATE)
    EndIf

    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_PAINT

Func WM_SIZE($hwnd, $iMsg, $wParam, $lParam)
    If $hwnd = $hGUI Then
        $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    EndIf

    Return 'GUI_RUNDEFMSG'
EndFunc


Func _Exit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0

    ; Clean up
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap_switch)
    _GDIPlus_GraphicsDispose($hGraphics)

    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_BrushDispose($hBrush_cadre_titre)

    ; Uninitialize GDI+
    _GDIPlus_Shutdown()

    Exit
EndFunc

 

OS6250-24M.jpg

Posted

I'm far from an expert on this, but it's probably the fact that you're constantly drawing 50 boxes of x number of elements to the screen every program cycle. I don't know if there's a way to update only a graphics object that has changed position since the last cycle. This would be my first area of investigation.

Posted (edited)

Ok I finally found a trick to do what I need.

Instead of redraw everything each cycle, I created a transparent gui on top of the main gui. And I drawn the frame I'm dragging on it. This cloned gui is destroy when the drag is finished. Took me some time to understand the basic mecanics of gdiplus...

Here is the code (not perfect) :

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



AutoItSetOption("MouseCoordMode", 2)

;Register callback
$hKey_Proc = DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")
$hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
$hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_MOUSE_LL, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)

Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"

Global $currentEvent[2]
Global $iLBUTTONDOWN = 0
Global $iRBUTTONDOWN = 0
Global $iMBUTTONDOWN = 0
Global $LRClickStatus = 0
Global $RLClickStatus = 0
Global $LRDrag = 0
Global $RLDrag = 0
Global $LMDrag = 0
Global $RMDrag = 0
Global $doubleClickTime = 400
Global $tPoint


Local Const $width = Int(@DesktopWidth * 0.8), $height = Int(@DesktopHeight * 0.8)

Global $max_width = 1900
Global $max_height = 1000


; Initialize GDI+
_GDIPlus_Startup()

Global $gui_clone = -1
Global $hGraphics_clone, $hBitmap_clone, $hBackbuffer_clone, $hHBitmap_clone, $hBrush_clone ; pour la gui clone

Global $hGUI = GUICreate("", $width, $height, -1, -1, BitOR($GUI_SS_DEFAULT_GUI,$WS_THICKFRAME,$WS_TABSTOP))
$aggrandissement = GUICtrlCreateButton("+", 10, 10, 20)
$diminution = GUICtrlCreateButton("-", 40, 10, 20)
GUISetState()



; main graphic and buffer
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($max_width, $max_height, $hGraphics)
Global $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, 1)
_GDIPlus_GraphicsSetInterpolationMode($hBackbuffer, 1)
_GDIPlus_GraphicsSetCompositingQuality($hBackbuffer, 1)
_GDIPlus_GraphicsSetPixelOffsetMode($hBackbuffer, 1)


Global $hBitmap_switch = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\OS6250-24M.jpg")
Global $iHeight_switch = _GDIPlus_ImageGetHeight($hBitmap_switch)


; exclude controls from GDI+ graphic region
Local $hRegion = _GDIPlus_RegionCreateFromRect(0, 0, $width, $height)
$aRect = ControlGetPos("", "", $aggrandissement)
_GDIPlus_RegionCombineRect($hRegion, $aRect[0], $aRect[1], $aRect[2], $aRect[3], 3)
$aRect = ControlGetPos("", "", $diminution)
_GDIPlus_RegionCombineRect($hRegion, $aRect[0], $aRect[1], $aRect[2], $aRect[3], 3)
_GDIPlus_GraphicsSetClipRegion($hGraphics, $hRegion)
_GDIPlus_RegionDispose($hRegion)


; Text format
Global $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000)
Global $hFormat = _GDIPlus_StringFormatCreate()
_GDIPlus_StringFormatSetAlign($hFormat, 1)
Global $hFamily = _GDIPlus_FontFamilyCreate("Arial")
Global $hFont = _GDIPlus_FontCreate($hFamily, 10, 2)

; for the frames drawing
Global $hPen = _GDIPlus_PenCreate(0xFF000000, 2)
Global $hBrush_cadre_titre = _GDIPlus_BrushCreateSolid(0x55FF0000)

Global $frame_width = 200
Global $frame_height = 200


Global $shift_X, $shift_Y
Global $move_inprogress = False
Global $index_stack
Global $iScale = 1


; creating array
Global $array[51][4]
$array[0][0] = 50

Local $startx = 50
Local $starty = 50
Local $guipos = WinGetPos($hGUI)
Local $intervalle_x = $guipos[2] / 10 ; width
Local $intervalle_y = $guipos[3] / 7 ; height

For $i = 1 To $array[0][0]

    ; auto positionning
    If Mod($i, 10) = 0 Then
        $x = $startx
        $y = $array[$i - 1][1] + $intervalle_y
    Else
        If $i - 1 = 0 Then ; first pass
            $x = $startx
            $y = $starty
        Else
            $x = $array[$i - 1][0] + $intervalle_x
            $y = $array[$i - 1][1]
        EndIf
    EndIf

    $array[$i][0] = $x
    $array[$i][1] = $y
    $array[$i][2] = "Hello world " & $i
    $array[$i][3] = "Bye world " & $i

Next

Global $fps = 0, $fps_maintimer, $fps_timer, $fps_diff
$fps_maintimer = TimerInit()

_DrawStack()


GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUIRegisterMsg($WM_SIZE, "WM_SIZE")

While 1
    $msg = GUIGetMsg()

    Switch $msg

        Case $GUI_EVENT_CLOSE
            _Exit()

        Case $GUI_EVENT_MAXIMIZE
            $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
            $winpos = WinGetPos($hGUI)
            ; exclude controls from GDI+ graphic region
            Local $hRegion = _GDIPlus_RegionCreateFromRect(0, 0, $winpos[2], $winpos[3])
            $aRect = ControlGetPos("", "", $aggrandissement)
            _GDIPlus_RegionCombineRect($hRegion, $aRect[0], $aRect[1], $aRect[2], $aRect[3], 3)
            $aRect = ControlGetPos("", "", $diminution)
            _GDIPlus_RegionCombineRect($hRegion, $aRect[0], $aRect[1], $aRect[2], $aRect[3], 3)
            _GDIPlus_GraphicsSetClipRegion($hGraphics, $hRegion)
            _GDIPlus_RegionDispose($hRegion)

        Case $aggrandissement
            $iScale = $iScale + 0.2
            _DrawStack($iScale)

        Case $diminution
            $iScale = $iScale - 0.2
            _DrawStack($iScale)

    EndSwitch

WEnd


Func _Create_CloneGUI($clone, $x_frame = -1, $y_frame = -1)
    Local $winpos = WinGetPos($hGUI)
    Local $width_border = _WinAPI_GetSystemMetrics($SM_CXSIZEFRAME)
    Local $height_menu = _WinAPI_GetSystemMetrics($SM_CYCAPTION)

    If $clone Then
        If $gui_clone = -1 Then

            $gui_clone = GUICreate("clone", $width, $height, $winpos[0] + $width_border, $winpos[1] + $height_menu + $width_border, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
            GUISetState()

            ; delete previous dragging frame drawing on the main gui
            $hBrush_clone = _GDIPlus_BrushCreateSolid(0xFFF0F0F0)
            _GDIPlus_GraphicsFillRect($hBackbuffer, $x_frame, $y_frame, $frame_width * $iScale, $frame_height * $iScale, $hBrush_clone)
            _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)

            ; new graphic for the cloned gui (with buffer)
            $hGraphics_clone = _GDIPlus_GraphicsCreateFromHWND($gui_clone)
            $hBitmap_clone = _GDIPlus_BitmapCreateFromGraphics($winpos[2] - 2 * $width_border, $winpos[3] - $height_menu - 2 * $width_border, $hGraphics_clone)
            $hBackbuffer_clone = _GDIPlus_ImageGetGraphicsContext($hBitmap_clone)

        EndIf

    Else
        If $gui_clone <> -1 Then

            _GDIPlus_BrushDispose($hBrush_clone)
            _GDIPlus_BitmapDispose($hBitmap_clone)
            _GDIPlus_GraphicsDispose($hGraphics_clone)
            _GDIPlus_GraphicsDispose($hBackbuffer_clone)
            _WinAPI_DeleteObject($hHBitmap_clone)

            GUIDelete($gui_clone)
            $gui_clone = -1
        EndIf
    EndIf
EndFunc


; Draw all the frames
Func _DrawStack($scale = 1, $index_en_cours = -1, $new_x = 0, $new_y = 0)
    Local $x, $y, $titre, $info, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hauteur_cadre_titre

    $fps_timer = TimerInit()
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFFF0F0F0)

    ; fps
    Local $tLayout_fps = _GDIPlus_RectFCreate(100, 10, 200, 20)
    _GDIPlus_GraphicsDrawStringEx($hBackbuffer, "FPS: " & StringFormat("%.2f", $fps), $hFont, $tLayout_fps, $hFormat, $hBrush)


    If $index_en_cours = -1 Then
        For $i = 1 To $array[0][0]
            $x = $array[$i][0]
            $y = $array[$i][1]
            $titre = $array[$i][2]
            $info = $array[$i][3]
            $tmp_cadre_largeur = Int($frame_width * $scale)
            $tmp_cadre_hauteur = Int($frame_height * $scale)
            $hauteur_cadre_titre = Int(16 * $scale) ; 15 pixels de haut

            $hFont = _GDIPlus_FontCreate($hFamily, Int(10 * $scale), 2)

            Local $tLayout_titre = _GDIPlus_RectFCreate($x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre)
            _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $titre, $hFont, $tLayout_titre, $hFormat, $hBrush)

            Local $tLayout_info = _GDIPlus_RectFCreate($x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre)
            _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $info, $hFont, $tLayout_info, $hFormat, $hBrush)

            _GDIPlus_GraphicsDrawRect($hBackbuffer, $x, $y, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hPen) ; cadre
            _GDIPlus_GraphicsFillRect($hBackbuffer, $x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre, $hBrush_cadre_titre) ; titre
            _GDIPlus_GraphicsDrawRect($hBackbuffer, $x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre, $hPen) ; info

            _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hBitmap_switch, $x + 2, $y + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch
            _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hBitmap_switch, $x + 2, $y + Int(($iHeight_switch / 2) * $scale) + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch

        Next
    Else
        For $i = 1 To $array[0][0]
            $x = $array[$i][0]
            $y = $array[$i][1]
            $titre = $array[$i][2]
            $info = $array[$i][3]
            $tmp_cadre_largeur = Int($frame_width * $scale)
            $tmp_cadre_hauteur = Int($frame_height * $scale)
            $hauteur_cadre_titre = Int(16 * $scale) ; 15 pixels de haut

            If $index_en_cours = $i Then ; le stack en cours de déplacement suit les mouvements de la souris, les autres ne bougent pas
                $x = $new_x
                $y = $new_y

                $hFont = _GDIPlus_FontCreate($hFamily, Int(10 * $scale), 2)

                Local $tLayout_titre = _GDIPlus_RectFCreate($x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre)
                _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $titre, $hFont, $tLayout_titre, $hFormat, $hBrush)

                Local $tLayout_info = _GDIPlus_RectFCreate($x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre)
                _GDIPlus_GraphicsDrawStringEx($hBackbuffer, $info, $hFont, $tLayout_info, $hFormat, $hBrush)

                _GDIPlus_GraphicsDrawRect($hBackbuffer, $x, $y, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hPen) ; cadre
                _GDIPlus_GraphicsFillRect($hBackbuffer, $x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre, $hBrush_cadre_titre) ; titre
                _GDIPlus_GraphicsDrawRect($hBackbuffer, $x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre, $hPen) ; info

                _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hBitmap_switch, $x + 2, $y + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch
                _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hBitmap_switch, $x + 2, $y + Int(($iHeight_switch / 2) * $scale) + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch

            EndIf
        Next
    EndIf

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0);, $max_width, $max_height) ; copy from backbuffer to visible graphic

    ; FPS
    $fps_diff = TimerDiff($fps_timer)
    If TimerDiff($fps_maintimer) > 999 Then ;calculate FPS
        $fps = Round(1000 / $fps_diff, 2)
        $fps_maintimer = TimerInit()
    EndIf
EndFunc


; Draw the dragging frame on the cloned transparent gui
Func _DrawStack_GUIClone($scale = 1, $index_en_cours = -1, $new_x = 0, $new_y = 0)
    Local $x, $y, $titre, $info, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hauteur_cadre_titre

    $x = $new_x
    $y = $new_y
    $titre = $array[$index_en_cours][2]
    $info = $array[$index_en_cours][3]
    $tmp_cadre_largeur = Int($frame_width * $scale)
    $tmp_cadre_hauteur = Int($frame_height * $scale)
    $hauteur_cadre_titre = Int(16 * $scale) ; 16 pixels de haut


    _GDIPlus_GraphicsClear($hBackbuffer_clone, 0x00000000)

    Local $hFont = _GDIPlus_FontCreate($hFamily, Int(10 * $scale), 2)

    Local $tLayout_titre = _GDIPlus_RectFCreate($x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre)
    _GDIPlus_GraphicsDrawStringEx($hBackbuffer_clone, $titre, $hFont, $tLayout_titre, $hFormat, $hBrush)

    Local $tLayout_info = _GDIPlus_RectFCreate($x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre)
    _GDIPlus_GraphicsDrawStringEx($hBackbuffer_clone, $info, $hFont, $tLayout_info, $hFormat, $hBrush)

    _GDIPlus_GraphicsDrawRect($hBackbuffer_clone, $x, $y, $tmp_cadre_largeur, $tmp_cadre_hauteur, $hPen) ; cadre
    _GDIPlus_GraphicsFillRect($hBackbuffer_clone, $x, $y, $tmp_cadre_largeur, $hauteur_cadre_titre, $hBrush_cadre_titre) ; titre
    _GDIPlus_GraphicsDrawRect($hBackbuffer_clone, $x, $y + $hauteur_cadre_titre, $tmp_cadre_largeur, $hauteur_cadre_titre, $hPen) ; info

    _GDIPlus_GraphicsDrawImageRect($hBackbuffer_clone, $hBitmap_switch, $x + 2, $y + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch
    _GDIPlus_GraphicsDrawImageRect($hBackbuffer_clone, $hBitmap_switch, $x + 2, $y + Int(($iHeight_switch / 2) * $scale) + Int(50 * $scale), $tmp_cadre_largeur - 4, Int(($iHeight_switch / 2) * $scale)) ; affichage de l'image du switch


    _GDIPlus_GraphicsDrawImage($hGraphics_clone, $hBitmap_clone, 0, 0) ; copy from backbuffer to visible graphic

    ; change the cloned gui to transparent
    ; should be placed here to be done each time your refresh the drawing (why ?)
    $hHBitmap_clone = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap_clone)
    _WinAPI_BitmapDisplayTransparentInGUI($hHBitmap_clone, $gui_clone)
    _WinAPI_DeleteObject($hHBitmap_clone)

EndFunc


Func _Mouse_Proc($nCode, $wParam, $lParam)
    Local $info, $mouseData, $time, $timeDiff

    If $nCode < 0 Then
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam)
        Return $ret[0]
    EndIf

    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
    $mouseData = DllStructGetData($info, 3)
    $time = DllStructGetData($info, 5)
    $timeDiff = $time - $currentEvent[1]

    Select
        Case $wParam = $WM_MOUSEMOVE
            ;Test for Drag in here

            If $currentEvent[0] <> "LDrag" Or $currentEvent[0] <> "LRDrag" Or $currentEvent[0] <> "LMDrag" Then

                If $iLBUTTONDOWN = 1 Then
                    $currentEvent[0] = "LDrag"

                    If $move_inprogress Then
                        $mouseX = MouseGetPos(0)
                        $mouseY = MouseGetPos(1)

                        ; draw only one frame, the one dragging
                        _DrawStack_GUIClone($iScale, $index_stack, $mouseX - $shift_X, $mouseY - $shift_Y)

                        $array[$index_stack][0] = $mouseX - $shift_X
                        $array[$index_stack][1] = $mouseY - $shift_Y

                    EndIf

                    If $iRBUTTONDOWN = 1 Then
                        $currentEvent[0] = "LRDrag"
                        $LRDrag = 2
                    EndIf
                EndIf
            EndIf

            If $currentEvent[0] <> "RDrag" Or $currentEvent[0] <> "RMDrag" Or $currentEvent[0] <> "LRDrag" Then
                If $iRBUTTONDOWN = 1 Then
                    $currentEvent[0] = "RDrag"
                EndIf
            EndIf

            If $currentEvent[0] <> "MDrag" Then
                If $iMBUTTONDOWN = 1 Then
                    $currentEvent[0] = "MDrag"
                    $currentEvent[1] = $time
                EndIf
            EndIf

            If $iRBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "RMDrag" Then
                $RMDrag = 2
                $currentEvent[0] = "RMDrag"
                $currentEvent[1] = $time
            EndIf

            If $iLBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "LMDrag" Then
                $LMDrag = 2
                $currentEvent[0] = "LMDrag"
                $currentEvent[1] = $time
            EndIf


        Case $wParam = $WM_MOUSEWHEEL

            If _WinAPI_HiWord($mouseData) > 0 Then
                ;Wheel Up
                $currentEvent[0] = "WheelUp"
                $currentEvent[1] = $time
            Else
                ;Wheel Down
                $currentEvent[0] = "WheelDown"
                $currentEvent[1] = $time
            EndIf

        Case $wParam = $WM_LBUTTONDOWN
            $mouseX = MouseGetPos(0)
            $mouseY = MouseGetPos(1)

            For $i = 1 To $array[0][0]
                If  $mouseX > $array[$i][0] And $mouseX < $array[$i][0] + $frame_width * $iScale And _
                    $mouseY > $array[$i][1] And $mouseY < $array[$i][1] + $frame_height * $iScale Then

                    $shift_X = $mouseX - $array[$i][0]
                    $shift_Y = $mouseY - $array[$i][1]

                    ; create cloned gui on top of main gui
                    _Create_CloneGUI(True, $mouseX - $shift_X, $mouseY - $shift_Y)

                    ; ... we can move
                    $move_inprogress = True
                    $index_stack = $i
                EndIf
            Next


            ; Register Button Down, check for Right/Left
            If $currentEvent[0] = "RClick" Then
                $LRClickStatus = 1
            EndIf

            $iLBUTTONDOWN = 1

        Case $wParam = $WM_LBUTTONUP
            ;Update $iLBUTTONDOWN
            $iLBUTTONDOWN = 0

            ;Test for Right/Left Click
            If $RLClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RLClick"
                $currentEvent[1] = $time
            EndIf
            If $currentEvent[0] = "LClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LDClick"
                $currentEvent[1] = $time
            EndIf

            ;Test for Drops
            If $currentEvent[0] = "LDrag" Then
                $currentEvent[0] = "LDrop"
                $currentEvent[1] = $time

                ; If movement in progress, then it's finished, left click released
                If $move_inprogress Then
                    $move_inprogress = False
                    _DrawStack($iScale) ; draw everything in main gui
                    _Create_CloneGUI(False) ; destroy cloned gui
                EndIf

            EndIf

            If $LRDrag = 2 And $iRBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf

            If $LMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $LMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "LClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $RLClickStatus = 0


        Case $wParam = $WM_RBUTTONDOWN
            ;Register Button Down
            If $currentEvent[0] = "LClick" Then
                $RLClickStatus = 1
            EndIf
            $iRBUTTONDOWN = 1

        Case $wParam = $WM_RBUTTONUP
            ;Test for Left, Right, and Right Doubleclick here
            ;Update $iRBUTTONDOWN
            $iRBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $LRClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LRClick"
                $currentEvent[1] = $time
            EndIf
            If $currentEvent[0] = "RClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "RDrag" Then
                $currentEvent[0] = "RDrop"
                $currentEvent[1] = $time
            EndIf

            If $LRDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf



            If $RMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "RClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $LRClickStatus = 0


        Case $wParam = $WM_MBUTTONDOWN
            ;Register Button Down
            $iMBUTTONDOWN = 1

        Case $wParam = $WM_MBUTTONUP
            ;Test for Middle Double Click here
            ;Update $iRBUTTONDOWN
            $iMBUTTONDOWN = 0
            ;Test for Right/Left Click
            If $currentEvent[0] = "MClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "MDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "MDrag" Then
                $currentEvent[0] = "MDrop"
                $currentEvent[1] = $time
            EndIf

            If $LMDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LMDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf



            If $RMDrag = 2 And $iRBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set MClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "MClick"
                $currentEvent[1] = $time
            EndIf

    EndSelect

;~  If $currentEvent[0] <> "" Then ConsoleWrite("event:"&$currentEvent[0] & @CRLF)

    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc


Func WM_PAINT($hwnd, $iMsg, $wParam, $lParam)
    If $hwnd = $hGUI Then
        _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
        _WinAPI_RedrawWindow($hwnd, 0, 0, $RDW_VALIDATE)
    EndIf

    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_PAINT


Func WM_SIZE($hwnd, $iMsg, $wParam, $lParam)
    If $hwnd = $hGUI Then
        $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    EndIf

    Return 'GUI_RUNDEFMSG'
EndFunc


; From UEZ ?
Func _WinAPI_BitmapDisplayTransparentInGUI(ByRef $hHBitmap, ByRef $hGUI, $iOpacity = 0xFF, $bReleaseGDI = True)
    If Not BitAND(GUIGetStyle($hGUI)[1], $WS_EX_LAYERED) = $WS_EX_LAYERED Then Return SetError(1, 0, 0)
    Local $tDim = DllStructCreate($tagBITMAP)
    If Not _WinAPI_GetObject($hHBitmap, DllStructGetSize($tDim), DllStructGetPtr($tDim)) Then Return SetError(2, 0, 0)
    Local $tSize = DllStructCreate($tagSIZE), $tSource = DllStructCreate($tagPOINT), $tBlend = DllStructCreate($tagBLENDFUNCTION)
    Local Const $hScrDC = _WinAPI_GetDC(0), $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC), $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    $tSize.X = $tDim.bmWidth
    $tSize.Y = $tDim.bmHeight
    $tBlend.Alpha = $iOpacity
    $tBlend.Format = 1
    _WinAPI_UpdateLayeredWindow($hGUI, $hScrDC, 0, DllStructGetPtr($tSize), $hMemDC, DllStructGetPtr($tSource), 0, DllStructGetPtr($tBlend), $ULW_ALPHA)
    _WinAPI_ReleaseDC(0, $hScrDC)
    _WinAPI_SelectObject($hMemDC, $hOld)
    _WinAPI_DeleteDC($hMemDC)
    If $bReleaseGDI Then _WinAPI_DeleteObject($hHBitmap)
    Return True
EndFunc


Func _Exit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0

    ; Clean up
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap_switch)
    _GDIPlus_GraphicsDispose($hGraphics)

    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_BrushDispose($hBrush_cadre_titre)


    ; Uninitialize GDI+
    _GDIPlus_Shutdown()

    Exit
EndFunc

 

If one of you have better ideas to make it work, I am obviously interested to read them :)

Edited by tatane

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...