#include-once
#include <Array.au3>
#include <WinAPI.au3>
#include <String.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>

#comments-start
	Example()
	Func Example()
	    
	    $GUI = GUICreate("Mein GUI",500,200)

	    ;Standart Defaults laden.
	    _4ern_ctrl_SetDefaults('reset')

	    ;Setzen die Defaults per 2D Array
	    Local $aDefaults[][] = [['bg_color', 0x3C639A], ['font_name', 'Verdana'], ['font_size', 10]]
	    _4ern_ctrl_SetDefaults($aDefaults)

	    ;neues Controll welches die Defaults besitzt
	    $btn1 = _4ern_ctrl_create('test',5,0)

	    ;neues Controll mit Defaults über parameter
	    $btn2 = _4ern_ctrl_create('test1',60,5,100,100,0x85BE9F)

	    ;neues Controll welches die neuen Defaults besitzt
	    $btn3 = _4ern_ctrl_create('test2',165,10)

	    ;Änderung der Schriftgröße per Funktion
	    _4ern_ctrl_SetDefaults('font_size',12)
	    $btn4 = _4ern_ctrl_create('test3',270,20)
	    $btn5 = _4ern_ctrl_create('test4',375,30)

	    ;Erstelle Array für Hover Buttons
	    Local $aHoverBtns[] = [$btn2, $btn3, $btn4, $btn5]

	    GUISetState(@SW_SHOW) ; Zeigt eine leere Dialogbox an

	    ; GUI starten, bis der Dialog beendet wird
	    while 1

	        Switch GUIGetMsg()
	        	case 0 
	        		;----------------------------------------------------------------------------------------------/
			    	; Hover Effekte
			    	;----------------------------------------------------------------------------------------------/
			    	_4ern_ctrl_hover($GUI,$aHoverBtns, $btn2, 0x3C639A, 0x85BE9F)
			    	
			    	;FlyOver auf dieses Label anwenden
			    	if _4ern_ctrl_hover($GUI,$aHoverBtns, $btn3, 0x3C639A, 0x85BE9F) = $btn3 then 
			    		_Example_onOver($GUI,$btn3)
			    	endif

			    	_4ern_ctrl_hover($GUI,$aHoverBtns, $btn4, 0x3C639A, 0x85BE9F)
			    	_4ern_ctrl_hover($GUI,$aHoverBtns, $btn5, 0x3C639A, 0x85BE9F)

	        	Case $GUI_EVENT_CLOSE
	        		exit
	        EndSwitch
	      
	    wend 
	EndFunc
	Func _Example_onOver($ParentGUI,$actionCtrl)
		
		;FlyOver GUI erstellen
		$GUI  = __FlyOver_GUI($ParentGUI, 400, 200, $actionCtrl, Default, Default, 0x3C639A)
		DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $GUI, "int", 150, "long", 0x00040001)
		
		_4ern_ctrl_create('sdfa sdf asd fasdf ',0,0)
		GUISetState(@SW_SHOWNOACTIVATE,$GUI)

		While 1
			$msg = GUIGetMsg()

			;wichtig um das FlyOver wieder zu verlassen
			if IsHWnd($GUI) = 0 then ExitLoop

		wend
	endfunc
#comments-end

; #FUNCTION# ===================================================================
; Name ..........: __FlyOver_GUI
; Description ...: 
; Parameters ....: $ParentGUI      = Handle der Übergeordneten GUI
; ...............: $_guiwidth      = Breite der FlyOver_GUI
; ...............: $gui_hight      = Höhe der FlyOver_GUI
;
; .....optional..: $actionCtrl     = Control-Id bei welchem FlyOver angezeigt wird 
;									 andernfalls, wird die Mausposition genutzt.
;
; .....optional..: $x_float_GUI    = x Positionierung der FlyOver_GUI
;                                  	 Default 	(right) wird rechts am $actionCtrl positioniert
;                                  	 			(left) wird links am $actionCtrl positioniert
;                                  	 Standard Positionangabe möglich zB. -1 oder 50 
;
; .....optional..: $y_float_GUI    = y Positionierung der FlyOver_GUI
;                                    Default 	(bottom) wird unterhalb am $actionCtrl positioniert
;                                    			(top) wird am oben Rand von $actionCtrl positioniert
;                                    Standard Positionangabe möglich zB. -1 oder 50 
;
; .....optional..: $color_bg       = Hintergrundfarbe der FlyOver_GUI
;
; .....optional..: $Style          = Default ($WS_POPUP)
;
; .....optional..: $exStlye        = Default (BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW, $WS_EX_MDICHILD))
;
; .....optional..: $drop_animation = Default (yes) 	Animation gemäß der Drop Positon.
;
;								     				Weiter Animationen 'https://github.com/MikaelMayer/reflex-tracer/blob/master/AnimationsTests.au3'
; .....optional..: $drop_duration  = Default (150) Dauer der Animation
;
; .....optional..: $drop_left      = Default (-10) Linke Maus Position um die FlyOver_GUI zu schließen
;
; .....optional..: $drop_right     = Default ($_guiwidth + 10) Rechte Maus Position um die FlyOver_GUI zu schließen
;
; .....optional..: $drop_top       = Default (-10) Obere Maus Position um die FlyOver_GUI zu schließen
;
; .....optional..: $drop_bottom    = Default ($gui_hight + 10) Untere Maus Position um die FlyOver_GUI zu schließen
; 
; WICHTIG........: In der jeweiligen While Schleife, muss folgende Befehl erfolgen, damit diese verlassen werden kann.
;				   if IsHWnd($deinGUIHandle) = 0 then ExitLoop
;
; Return values .: GUI Handle
; @error.........: 1 GUI konnte nicht erstellt werden
; Author ........: 4ern.de
; ==============================================================================
func __FlyOver_GUI($ParentGUI, $_guiwidth, $gui_hight, _ 
					$actionCtrl     = Default, _  
					$x_float_GUI    = Default, _ 
					$y_float_GUI    = Default, _ 
					$color_bg       = Default, _ 
					$Style          = Default, _ 
					$exStlye        = Default, _ 
					$drop_animation = Default, _ 
					$drop_duration  = Default, _ 
					$drop_left      = Default, _
					$drop_right     = Default, _
					$drop_top       = Default, _
					$drop_bottom    = Default)

	;----------------------------------------------------------------------------------------------/
	; Deklaration Defaults
	;----------------------------------------------------------------------------------------------/
		if $actionCtrl  = Default then $actionCtrl     = 0
		if $x_float_GUI = Default then $x_float_GUI    = 'right'
		if $y_float_GUI = Default then $y_float_GUI    = 'bottom' 
		if $color_bg    = Default then $color_bg       = 0xFFFFFF
		if $Style       = Default then $Style          = $WS_POPUP
		if $exStlye     = Default then $exStlye        = BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW, $WS_EX_MDICHILD)
		
	;----------------------------------------------------------------------------------------------/
	; Floats
	;----------------------------------------------------------------------------------------------/
		
		if IsHWnd(GUICtrlGetHandle($actionCtrl)) then
			Local $pos_ParentGUI = ControlGetPos($ParentGUI, '', $actionCtrl)
			Switch $x_float_GUI
				Case 'left'
					$x_float_GUI =  $pos_ParentGUI[0] + $pos_ParentGUI[2] + 3
				Case 'right'
					$x_float_GUI =  $pos_ParentGUI[0] + 3
			EndSwitch
			Switch $y_float_GUI
				Case 'top'
					$y_float_GUI = 0
				Case 'bottom'
					$y_float_GUI =  $pos_ParentGUI[1] + $pos_ParentGUI[3] + 3
			EndSwitch
		Else
			$oldOpt = AutoItSetOption( 'MouseCoordMode', 0)
			$x_float_GUI = MouseGetPos(0)
			$y_float_GUI = MouseGetPos(1)
			AutoItSetOption( 'MouseCoordMode', $oldOpt)
		endif
			
	;----------------------------------------------------------------------------------------------/
	; Erstellung GUI
	;----------------------------------------------------------------------------------------------/
		$GUI = GUICreate('', $_guiwidth, $gui_hight, $x_float_GUI, $y_float_GUI, $Style, $exStlye ,$ParentGUI)
		if @error then return SetError(1, 0, $GUI)
		GUISetBkColor($color_bg)

	;----------------------------------------------------------------------------------------------/
	; Hide Animation
	;----------------------------------------------------------------------------------------------/
	;----------------------------------------------------------------------------------------------/
	; Deklaration Defaults
	;----------------------------------------------------------------------------------------------/
		if $drop_animation = Default then $drop_animation = 'yes'
		if $drop_duration  = Default then $drop_duration  = 150
		if $drop_left      = Default then $drop_left      = - 10
		if $drop_right     = Default then $drop_right     = $_guiwidth   + 10
		if $drop_top       = Default then $drop_top       = - 10
		if $drop_bottom    = Default then $drop_bottom    = $gui_hight   + 10
		
		Local $a_Parameter[] = [$GUI, $actionCtrl, $drop_animation, $drop_duration, $drop_left, $drop_right, $drop_top, $drop_bottom]
		__flyOver_drop('start', $a_Parameter)

		return $GUI
endfunc

;----------------------------------------------------------------------------------------------/
; __FlyOver_GUI ADLIBREGISTER
;----------------------------------------------------------------------------------------------/
func __flyOver_drop($action = 'stop', $a_Parameter = 0)
	
	Local Static $a_AdlibParams[1]
	Local Static $lastAdlib = 0

	Switch $action
		Case 'start'
			if IsArray($a_Parameter) then
				$lastAdlib += 1
				_ArrayAdd($a_AdlibParams, $a_Parameter)
				__FlyOver_GUI_drop_Adlib('setData', $a_Parameter)
				AdlibRegister('__FlyOver_GUI_drop_Adlib_withOutParms')
			endif
		Case 'stop'
			_ArrayDelete($a_AdlibParams, $lastAdlib)
			$lastAdlib -= 1		
			if IsArray($a_AdlibParams) then
				$array = $a_AdlibParams[$lastAdlib]
				if IsArray($array) then
					__FlyOver_GUI_drop_Adlib('setData', $array)
					AdlibRegister('__FlyOver_GUI_drop_Adlib_withOutParms')
				endif
			endif
	EndSwitch
endfunc

;----------------------------------------------------------------------------------------------/
; __FlyOver_GUI Drop Funktion
;----------------------------------------------------------------------------------------------/
func __FlyOver_GUI_drop_Adlib_withOutParms()
	__FlyOver_GUI_drop_Adlib()
	return
endfunc

func __FlyOver_GUI_drop_Adlib($action = '', $a_Parameter = 0)

	Local Static $aParams

	if IsDeclared('action') then
		if $action = 'setData' then
			$aParams = 0
			$aParams = $a_Parameter
			return 1
		endif
	endif

	if IsArray($aParams) then 

		;----------------------------------------------------------------------------------------------/
		; Parent Fenster erkennen
		;----------------------------------------------------------------------------------------------/
			$parent_hWnd = _WinAPI_GetParent($aParams[0])
			if IsHWnd($parent_hWnd)	then 
				$aMainCursor       = GUIGetCursorInfo($parent_hWnd)
				if $aMainCursor[4] = $aParams[1] then return
			endif

		;----------------------------------------------------------------------------------------------/
		; GUI Drop-Bereich
		;----------------------------------------------------------------------------------------------/
		
		Local $aCursor = GUIGetCursorInfo($aParams[0])
		if @error then return

		Select
			;Drop Left
			Case $aCursor[0] < $aParams[4]
				;~ ConsoleWrite('drop Left' & @CRLF)
				$autoAnimation = 0x00050002
			;Drop Right
			Case $aCursor[0] > $aParams[5]
				;~ ConsoleWrite('drop Right' & @CRLF)
				$autoAnimation = 0x00050001
			;Drop Top
			Case $aCursor[1] < $aParams[6]
				;~ ConsoleWrite('drop Top' & @CRLF)
				$autoAnimation = 0x00050008
			;Drop Bottom
			Case $aCursor[1] > $aParams[7]
				;~ ConsoleWrite('drop Bottom' & @CRLF)
				$autoAnimation = 0x00050008
			case Else
				return
		EndSelect

		if $aParams[2] = 'yes' then 
			DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $aParams[0], "int", $aParams[3], "long", $autoAnimation)
		Else
			DllCall("user32.dll", "int", "AnimateWindow", "hwnd", $aParams[0], "int", $aParams[3], "long", $aParams[2])
		endif

		AdlibUnRegister('__FlyOver_GUI_drop_Adlib')
		$ret = GUIDelete($aParams[0])

		sleep(50)
		__flyOver_drop('stop')

	endif
endfunc

;----------------------------------------------------------------------------------------------/
; #FUNCTION# ===================================================================
; Name ..........: _4ern_ctrl_hover
; Description ...: Mouse Hover Funktion
; Parameters ....: $mainGUI            = GUI Handle
; ...............: $aCtrls             = Array mit allen Hover Controlls
; ...............: $ctrl               = Control auf dem das Hover angewendet soll
; .....optional..: $Hover_bg_color     = Hintergrund Farbe des Hovers
; .....optional..: $nonHover_bg_color  = Hintergrund Farbe des Controls
; .....optional..: $hover_font_color   = Schriftfarbe des Hovers
; .....optional..: $noHover_font_color = Schriftfarbe des Controls
; Requirement ...: GUIConstantsEx.au3
; Return values .: $activeCtrlID 	   = ctrlId des aktuellen Hovers
; Author ........: 4ern.de
; ==============================================================================
func _4ern_ctrl_hover($GUI, byref $aCtrls, $ctrl, $Hover_bg_color = false, $nonHover_bg_color = false, $hover_font_color = false, $noHover_font_color = false)

	Local Static $activeCtrlID, $LableHovered, $GUI_old, $aCtrls_old, $nonHover_bg_color_old, $noHover_font_color_old, $ctrl_old

	;----------------------------------------------------------------------------------------------/
	; Alte Hovers zwischen Speichern.
	;----------------------------------------------------------------------------------------------/
	if $GUI_old <> $GUI then 
		for $i = 0 to Ubound($aCtrls_old) -1
			if $aCtrls_old[$i] = $ctrl_old then ContinueLoop
			if $nonHover_bg_color <> false then GUICtrlSetBkColor($aCtrls_old[$i], $nonHover_bg_color_old)
			if $noHover_font_color <> false then GUICtrlSetColor($aCtrls_old[$i], $noHover_font_color_old)
		next
		$GUI_old                = $GUI
		$aCtrls_old             = $aCtrls
		$nonHover_bg_color_old  = $nonHover_bg_color
		$noHover_font_color_old = $noHover_font_color
		$ctrl_old               = $ctrl
		return
	endif
	
	;----------------------------------------------------------------------------------------------/
	; Ermittle den Cursor auf der GUI
	;----------------------------------------------------------------------------------------------/
	Local $aCursor = GUIGetCursorInfo($GUI)
	If Not IsArray($aCursor) Then return	

	;----------------------------------------------------------------------------------------------/
	; Setze Ctrls zurück ...
	;----------------------------------------------------------------------------------------------/
		;Cursor Control-ID ist 0 und Hover ist aktiv
		if $aCursor[4] = 0 and $LableHovered = True then
			for $i = 0 to Ubound($aCtrls) -1
				if $nonHover_bg_color <> false then GUICtrlSetBkColor($aCtrls[$i], $nonHover_bg_color)
				if $noHover_font_color <> false then GUICtrlSetColor($aCtrls[$i], $noHover_font_color)
			next 
			$LableHovered = False
			$activeCtrlID = 0
			return
		endif

		;Cursor Control-ID stimmt nicht mit $activeCtrlID überein und Hover ist aktiv
		if $aCursor[4] <> $activeCtrlID and $LableHovered = True then 
			for $i = 0 to Ubound($aCtrls) -1
				if $nonHover_bg_color <> false then GUICtrlSetBkColor($aCtrls[$i], $nonHover_bg_color)
				if $noHover_font_color <> false then GUICtrlSetColor($aCtrls[$i], $noHover_font_color)
			next 
			$LableHovered = False
			$activeCtrlID = 0
			return
		endif

		;Wenn eine weitere GUI dazu kommt ist $aCursor[4] = 0 und $LableHovered = Flase
		if $aCursor[4] = 0 and $LableHovered = false then
			$oldOpt = AutoItSetOption( 'PixelCoordMode', 0)
			for $i = 0 to Ubound($aCtrls) -1
				$hwnd = GUICtrlGetHandle($aCtrls[$i])
				$bgColor = PixelGetColor(1, 1 , $hwnd)
				if $bgColor = $Hover_bg_color then 
					if $nonHover_bg_color <> false then GUICtrlSetBkColor($aCtrls[$i], $nonHover_bg_color)
					if $noHover_font_color <> false then GUICtrlSetColor($aCtrls[$i], $noHover_font_color)
				endif
			next 
			AutoItSetOption( 'PixelCoordMode', $oldOpt)
			$LableHovered = False
			$activeCtrlID = 0
			return
		endif

	;----------------------------------------------------------------------------------------------/
	; Eigentlicher Hovereffekt
	;----------------------------------------------------------------------------------------------/
		if $aCursor[4] = $ctrl then
			if $LableHovered = False then 
				if $Hover_bg_color <> false then GUICtrlSetBkColor($ctrl, $Hover_bg_color)
				if $hover_font_color <> false then GUICtrlSetColor($ctrl, $hover_font_color)
				$LableHovered = True
				$activeCtrlID = $ctrl
			endif
		endif

	;----------------------------------------------------------------------------------------------/
	; Setze vorherige Werte
	;----------------------------------------------------------------------------------------------/
		$GUI_old                = $GUI
		$aCtrls_old             = $aCtrls
		$nonHover_bg_color_old  = $nonHover_bg_color
		$noHover_font_color_old = $noHover_font_color
		$ctrl_old               = $ctrl

	return $activeCtrlID
endfunc

; #FUNCTION# ===================================================================
; Name ..........: _4ern_ctrl_create
; Description ...: 
; Parameters ....: $txt
; ...............: $left
; ...............: $top
;
; .....optional..: $width
; .....optional..: $height
; .....optional..: $bg_color
; .....optional..: $font_color
; .....optional..: $font_name
; .....optional..: $font_size
; .....optional..: $font_weight
; .....optional..: $font_attribut
; .....optional..: $cursor
; .....optional..: $style
; .....optional..: $exStyle
; Requirement ...: 
; Return values .: 
; Author ........: 4ern.de
; ==============================================================================
func _4ern_ctrl_create($txt, $left = 0, $top = 0, _
						$width 		   = Default, _
						$height        = Default, _
						$bg_color      = Default, _
						$font_color    = Default, _
						$font_name     = Default, _
						$font_size     = Default, _
						$font_weight   = Default, _
						$font_attribut = Default, _
						$cursor        = Default, _
						$state         = Default, _
						$style         = Default, _
						$exStyle       = Default)

	;----------------------------------------------------------------------------------------------/
	; Defaulte werte
	;----------------------------------------------------------------------------------------------/
	Local Static $firstCtrl = True
	Local $aDefaults[12] = [-1,-1,false,0xFFFFFF,'Arial',8.5,400,-1,Default,0,Default,Default]
	Local Static $aValues[12]
	Local $aParams[12]   = 	[ _ 
								$width, _ 
								$height, _ 
								$bg_color, _ 
								$font_color, _ 
								$font_name, _ 
								$font_size, _ 
								$font_weight, _ 
								$font_attribut, _ 
								$cursor, _ 
								$state, _ 
								$style, _ 
								$exStyle _
							]

	;----------------------------------------------------------------------------------------------/
	; Defaults zurücksetzen
	;----------------------------------------------------------------------------------------------/
	if $txt = '4ernSetResetDefaults' then 
		for $i = 0 to Ubound($aValues) -1
			$aValues[$i] = $aDefaults[$i]
		next
		return
	endif

	;----------------------------------------------------------------------------------------------/
	; Erster Funktions Aufruf
	;----------------------------------------------------------------------------------------------/
	if $firstCtrl = True then 
		$firstCtrl = False
		for $i = 0 to Ubound($aValues) -1
			if $aParams[$i] = Default then 
				$aValues[$i] = $aDefaults[$i]
			else
				$aValues[$i] = $aParams[$i]
			endif
		next
	endif

	;----------------------------------------------------------------------------------------------/
	; Wenn nur die Defaults gesetzt werden sollen.
	;----------------------------------------------------------------------------------------------/
	for $i = 0 to Ubound($aValues) -1
		if $aParams[$i] <> Default or StringInStr($aParams[$i], 'Default') = 0 then 
			$aValues[$i] = $aParams[$i]
		endif
	next
	if $txt = '4ernSetDefaults' then return

	;----------------------------------------------------------------------------------------------/
	; Erstelle Controll
	;----------------------------------------------------------------------------------------------/
	$ctrl = GUICtrlCreateLabel($txt, $left, $top, $aValues[0], $aValues[1], $aValues[10], $aValues[11])
	if $aValues[2]<> False then GUICtrlSetBkColor($ctrl, $aValues[2])
	if $aValues[3]<> False then GUICtrlSetColor($ctrl, $aValues[3])
	GUICtrlSetFont($ctrl, $aValues[5], $aValues[6], $aValues[7], $aValues[4])
	GUICtrlSetCursor($ctrl,$aValues[8])
	GUICtrlSetState($ctrl, $aValues[9])

	return $ctrl
endfunc

func _4ern_ctrl_SetDefaults($key, $Value = 0)
	
	Local $aFuncParams[][] = [ _ 
								[Default,'width'], _
								[Default,'height'], _
								[Default,'bg_color'], _
								[Default,'font_color'], _
								[Default,'font_name'], _
								[Default,'font_size'], _
								[Default,'font_weight'], _
								[Default,'font_attribut'], _
								[Default,'cursor'], _
								[Default,'state'], _
								[Default,'style'], _
								[Default,'exStyle'] _
							 ]

	Local $txt = '4ernSetDefaults'
	
	;----------------------------------------------------------------------------------------------/
	; Defaults alle zurücksetzen.
	;----------------------------------------------------------------------------------------------/
	if $key = 'reset' then 
		_4ern_ctrl_create('4ernSetResetDefaults', 0, 0)
		return
	endif

	;----------------------------------------------------------------------------------------------/
	; Settings setzen
	;----------------------------------------------------------------------------------------------/
	If IsArray($key) then 
		if UBound($key, 2) < 2 then Return SetError(1)
		for $i = 0 to Ubound($aFuncParams) -1
			for $ii = 0 to Ubound($key) -1
				$s_prop_1 = _StringProper($aFuncParams[$i][1])
				$s_prop_2 = _StringProper($key[$ii][0])
				if StringInStr($s_prop_1,$s_prop_2,1) <> 0 then
					$aFuncParams[$i][0] = $key[$ii][1]
					ContinueLoop 2
				endif
			next
		next
	Else
		for $i = 0 to Ubound($aFuncParams) -1
			if StringInStr($aFuncParams[$i][1], $key) <> 0 then
				$aFuncParams[$i][0] = $Value
				ExitLoop
			endif
		next
	endif

	;----------------------------------------------------------------------------------------------/
	; Setze Defaults
	;----------------------------------------------------------------------------------------------/
	_4ern_ctrl_create($txt, 0, 0, _
							$aFuncParams[0][0], _
							$aFuncParams[1][0], _
							$aFuncParams[2][0], _
							$aFuncParams[3][0], _
							$aFuncParams[4][0], _
							$aFuncParams[5][0], _
							$aFuncParams[6][0], _
							$aFuncParams[7][0], _
							$aFuncParams[8][0], _
							$aFuncParams[9][0], _
							$aFuncParams[10][0], _
							$aFuncParams[11][0])
	return
endfunc


