#Region - TimeStamp
; 2012-08-20 00:36:45   v 0.2
#EndRegion - TimeStamp

#cs

- Grafische Darstellung eines sich ändernden (Meß)Wertes
- "Aktualisierungsfenster" läuft von links nach rechts über den Darstellungsbereich und überschreibt alte Werte mit den neuen

Funktionsübersicht:

	_GraphCtrl_Create

	_GraphCtrl_VScaleSet

	_GraphCtrl_HScaleSet

	_GraphCtrl_SetColor

	_GraphCtrl_SetDensity

	_GraphCtrl_SetHelpline

Events:

	ID ist mit GuiGetMsg oder GuiCtrlSetOnEvent zu verwenden.
	Mit GuiCtrlRead(ID) sind folgende Ereignisse auswertbar:

		$WM_LBUTTONDOWN
		$WM_LBUTTONUP
		$WM_RBUTTONDOWN
		$WM_RBUTTONUP
		$WM_MBUTTONDOWN
		$WM_MBUTTONUP

#ce


#include-once
#Include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Timers.au3>
#Include <WindowsConstants.au3>

OnAutoItExitRegister('__GraphCtrlDispose')
Global $__aDC[1][2] = [[0]]         ; == Manage Buffers
Global $__aGraphCtrl[1][5] = [[0]]  ; == Manage Controls

Global Const $__HC_ACTION = 0
Global $__MOUSEPROC_ACTIVE = 0
Global $__hSTUB__MouseProcGraph, $__hMOD_GRAPH, $__hHOOK_MOUSE_GRAPH
Global $__iTop, $__iLeft
_SystemGetWindowBorder($__iTop, $__iLeft)


;===============================================================================
; Function Name....: _GraphCtrl_Create
; Description......: Creates an Graph Control, starts mouse procedure and GDIplus, if required
; Parameter(s).....: $_hGui            GUI-Handle there control will create
; .................: $_iX              x-Position on GUI
; .................: $_iY              y-Position on GUI
; .................: $_iW              Control width
; .................: $_iH              Control heighth
; .................: $_iEpochTime      Time in seconds to draw graph over full width (default=10s)
; .................: $_iDensity        Count of value points by pixel (default=0.25)
; .................: $_iPenWidth       Width of pen (takes effect for graph and axes)
; .................: $_iARGB_BG        Color background
; .................: $_iARGB_Graph     Color graph
; .................: $_iARGB_Axes      Color axes
; .................: $_iARGB_PreDraw   Color
; .................: $_iARGB_Help
; Return Value(s)..: Control ID, to use with GuiGetMsg or GuiCtrlSetOnEvent
; .................: With GuiCtrlRead(ID) you can get events: $WM_LBUTTONDOWN, $WM_LBUTTONUP, $WM_RBUTTONDOWN, $WM_RBUTTONUP, $WM_MBUTTONDOWN, $WM_MBUTTONUP
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_Create($_hGui, $_iX, $_iY, $_iW, $_iH, $_iEpochTime=10, $_iDensity=0.25, $_iPenWidth=1, $_iARGB_BG=0xFF006400, $_iARGB_Graph=0xFFFFD700, $_iARGB_Axes=0xFFFFFFFF, $_iARGB_PreDraw=0xFFFFFFFF, $_iARGB_Help=0xFF22AA22)
	If $__MOUSEPROC_ACTIVE = 0 Then __GraphCtrl_Startup()
	If $_iDensity  = -1 Then $_iDensity  = 0.25
	If $_iPenWidth = -1 Then $_iPenWidth = 1
	__ObjBufferRegister($_hGui)

	Local $oCtrl = ObjCreate('Scripting.Dictionary')
	With $oCtrl
		.Add('X'              , $_iX)
		.Add('Y'              , $_iY)
		.Add('W'              , $_iW)
		.Add('H'              , $_iH)
		.Add('EpochTime'      , $_iEpochTime)
		.Add('Intervall'      , $_iEpochTime * 1000 / $oCtrl.Item('W') / $_iDensity)
		.Add('TimeStamp'      , 0)
		.Add('Density'        , $_iDensity)
		.Add('PenWidth'       , $_iPenWidth)
		.Add('BrushBG'        , _GDIPlus_BrushCreateSolid($_iARGB_BG))
		.Add('PenGraph'       , _GDIPlus_PenCreate($_iARGB_Graph, $_iPenWidth))
		.Add('PenPredraw'     , _GDIPlus_PenCreate($_iARGB_PreDraw))
		.Add('PenHelp'        , _GDIPlus_PenCreate($_iARGB_Help))
		.Add('PenAxes'        , _GDIPlus_PenCreate($_iARGB_Axes, $_iPenWidth))
		.Add('First'          , True)
		.Add('CoordIndex'     , 1)
		.Add('UB'             , 1)
	EndWith
	Local $aCoord[Int($oCtrl.Item('W') * $oCtrl.Item('Density'))][2]
	$oCtrl.Item('UB') = UBound($aCoord)
	Local $aHelpLine[1] = [0]
	Local $aCtrl[3] = [$oCtrl, $aCoord, $aHelpLine]
	Local $aVScale[1] = [0]
	Local $aHScale[1] = [0]
	Local $iDummy = GUICtrlCreateDummy()
	$__aGraphCtrl[0][0] += 1
	ReDim $__aGraphCtrl[$__aGraphCtrl[0][0] +1][5]
	$__aGraphCtrl[$__aGraphCtrl[0][0]][0] = $iDummy
	$__aGraphCtrl[$__aGraphCtrl[0][0]][1] = $aCtrl
	$__aGraphCtrl[$__aGraphCtrl[0][0]][2] = $_hGui
	$__aGraphCtrl[$__aGraphCtrl[0][0]][3] = $aVScale
	$__aGraphCtrl[$__aGraphCtrl[0][0]][4] = $aHScale
	Return $iDummy
EndFunc  ;==>_GraphCtrl_Create

;===============================================================================
; Function Name....: _GraphCtrl_VScaleSet
; Description......: Sets vertical scale for graph control or deactivate scaling
; Parameter(s).....: $_iID             Control ID, you've gotten from _GraphCtrl_Create
; .................: $_fActive         Scaling vertical is active (default=1)
; .................: $_vVal            String or Array with pixel values to set as scale, -1 (default) ignores this param
; .................: $_iStepPercent    Value in percent for every step in scale, -1 (default) sets it to 10
; Return Value(s)..: Nothing
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_VScaleSet($_iID, $_fActive=1, $_vVal=-1, $_iStepPercent=-1)
	Local $iIndexCtrl = __GraphCtrl_GetIndex($_iID)
	Local $aCtrl      = $__aGraphCtrl[$iIndexCtrl][1]
	Local $aVScale    = $__aGraphCtrl[$iIndexCtrl][3]
	Local $oCtrl      = $aCtrl[0]
	Local $sVal, $iCount, $iStep
	If $_fActive = 0 Then
		Local $aTmp[1] = [0]
		$__aGraphCtrl[$iIndexCtrl][3] = $aTmp
		Return
	EndIf
	If $_vVal = -1 Then
		If $_iStepPercent = -1 Then $_iStepPercent = 10
		If $_iStepPercent > 50 Then $_iStepPercent = 50
		$iCount = Int(100 / $_iStepPercent)
		$iStep = $oCtrl.Item('H') / $iCount
		ReDim $aVScale[$iCount +1]
		$aVScale[0] = $iCount
		For $i = 1 To $aVScale[0]
			$aVScale[$i] = $i * $iStep
		Next
		$__aGraphCtrl[$iIndexCtrl][3] = $aVScale
	Else
		If IsArray($_vVal) Then
			ReDim $aVScale[UBound($_vVal) +1]
			$aVScale[0] = UBound($_vVal)
			For $i = 0 To $aVScale[0] -1
				$aVScale[$i +1] = $_vVal[$i]
			Next
			$__aGraphCtrl[$iIndexCtrl][3] = $aVScale
		Else
			$__aGraphCtrl[$iIndexCtrl][3] = StringSplit($_vVal, ',')
		EndIf
	EndIf
EndFunc  ;==>_GraphCtrl_VScaleSet

;===============================================================================
; Function Name....: _GraphCtrl_HScaleSet
; Description......: Sets horizontal scale for graph control or deactivate scaling
; Parameter(s).....: $_iID             Control ID, you've gotten from _GraphCtrl_Create
; .................: $_fActive         Scaling horizontal is active (default=1)
; .................: $_fSeconds        Use count of epoche time for scaling (default=1), ignore with 0
; .................: $_vVal            String or Array with pixel values to set as scale, -1 (default) ignores this param
; .................: $_iStepPercent    Value in percent for every step in scale, -1 (default) sets it to 10
; Return Value(s)..: Nothing
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_HScaleSet($_iID, $_fActive=1, $_fSeconds=1, $_vVal=-1, $_iStepPercent=-1)
	Local $iIndexCtrl = __GraphCtrl_GetIndex($_iID)
	Local $aCtrl      = $__aGraphCtrl[$iIndexCtrl][1]
	Local $aHScale    = $__aGraphCtrl[$iIndexCtrl][4]
	Local $oCtrl      = $aCtrl[0]
	Local $sVal, $iCount, $iStep
	If $_fActive = 0 Then
		Local $aTmp[1] = [0]
		$__aGraphCtrl[$iIndexCtrl][4] = $aTmp
		Return
	EndIf
	If $_fSeconds = 1 Then
		$iCount = $oCtrl.Item('EpochTime')
		$iStep = $oCtrl.Item('W') / $iCount
		ReDim $aHScale[$iCount +1]
		$aHScale[0] = $iCount
		For $i = 1 To $aHScale[0]
			$aHScale[$i] = $i * $iStep
		Next
		$__aGraphCtrl[$iIndexCtrl][4] = $aHScale
	ElseIf $_vVal = -1 Then
		If $_iStepPercent = -1 Then $_iStepPercent = 10
		If $_iStepPercent > 50 Then $_iStepPercent = 50
		$iCount = Int(100 / $_iStepPercent)
		$iStep = $oCtrl.Item('W') / $iCount
		ReDim $aHScale[$iCount +1]
		$aHScale[0] = $iCount
		For $i = 1 To $aHScale[0]
			$aHScale[$i] = $i * $iStep
		Next
		$__aGraphCtrl[$iIndexCtrl][4] = $aHScale
	Else
		If IsArray($_vVal) Then
			ReDim $aHScale[UBound($_vVal) +1]
			$aHScale[0] = UBound($_vVal)
			For $i = 0 To $aHScale[0] -1
				$aHScale[$i +1] = $_vVal[$i]
			Next
			$__aGraphCtrl[$iIndexCtrl][4] = $aHScale
		Else
			$__aGraphCtrl[$iIndexCtrl][4] = StringSplit($_vVal, ',')
		EndIf
	EndIf
EndFunc  ;==>_GraphCtrl_HScaleSet

;===============================================================================
; Function Name....: _GraphCtrl_SetColor
; Description......: Sets horizontal scale for graph control or deactivate scaling
; Parameter(s).....: $_iID          Control ID, you've gotten from _GraphCtrl_Create
; .................: $_sParam       Parameter, whose value are to be changed, may be:
; .................:                	BrushBG
; .................:                	PenGraph
; .................:                	PenPredraw
; .................:                	PenHelp
; .................:                	PenAxes
; .................: $_iARGB        Color (ARGB) for selected param
; Return Value(s)..: 0 and @error=1 if $_sParam not exists
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_SetColor($_iID, $_sParam, $_iARGB)
	Local $iIndexCtrl = __GraphCtrl_GetIndex($_iID)
	Local $aCtrl      = $__aGraphCtrl[$iIndexCtrl][1]
	Local $oCtrl      = $aCtrl[0]
	If Not $oCtrl.Exists($_sParam) Then Return SetError(1,0,0)
	If $_sParam = 'BrushBG' Then
		_GDIPlus_BrushDispose($oCtrl.Item($_sParam))
		$oCtrl.Item($_sParam) = _GDIPlus_BrushCreateSolid($_iARGB)
	Else
		_GDIPlus_PenDispose($oCtrl.Item($_sParam))
		Local $iWidth = 1
		If $_sParam = 'PenGraph' Or $_sParam = 'PenAxes' Then $iWidth = $oCtrl.Item('PenWidth')
		$oCtrl.Item($_sParam) = _GDIPlus_PenCreate($_iARGB, $iWidth)
	EndIf
	$aCtrl[0] = $oCtrl
	$__aGraphCtrl[$iIndexCtrl][1] = $aCtrl
EndFunc  ;==>_GraphCtrl_SetColor

;===============================================================================
; Function Name....: _GraphCtrl_SetDensity
; Description......: Sets density of drawing as value points by pixel
; Parameter(s).....: $_iID          Control ID, you've gotten from _GraphCtrl_Create
; .................: $_iDensity     Density of drawing (default=0.25)
; Return Value(s)..: Nothing
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_SetDensity($_iID, $_iDensity=0.25)
	Local $iIndexCtrl         = __GraphCtrl_GetIndex($_iID)
	Local $oBuffer            = __GetBuffer($__aGraphCtrl[$iIndexCtrl][2])
	Local $aCtrl              = $__aGraphCtrl[$iIndexCtrl][1]
	Local $oCtrl              = $aCtrl[0]
	$oCtrl.Item('Density')    = $_iDensity
	$oCtrl.Item('Intervall')  = $oCtrl.Item('EpochTime') * 1000 / $oCtrl.Item('W') / $_iDensity
	$oCtrl.Item('TimeStamp')  = 0
	Local $aCoord[Int($oCtrl.Item('W') * $_iDensity)][2]
	$oCtrl.Item('UB')         = UBound($aCoord)
	$oCtrl.Item('First')      = True
	$oCtrl.Item('CoordIndex') = 1
	_GDIPlus_GraphicsFillRect($oBuffer.Item('Context'), 0, 0, $oCtrl.Item('W'), $oCtrl.Item('H'), $oCtrl.Item('BrushBG'))
	$aCtrl[0] = $oCtrl
	$aCtrl[1] = $aCoord
	$__aGraphCtrl[$iIndexCtrl][1] = $aCtrl
EndFunc  ;==>_GraphCtrl_SetColor

;===============================================================================
; Function Name....: _GraphCtrl_SetHelpline
; Description......: Sets or deactivates horizontal helplines
; Parameter(s).....: $_iID          Control ID, you've gotten from _GraphCtrl_Create
; .................: $_iCount       Count of help lines (without closing line on top), 0 deactivates showing
; .................: $_vVal         String or Array with pixel values to set
; Return Value(s)..: 0 and @error=1 if no valid value for $_iCount or $_vVal passed
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_SetHelpline($_iID, $_iCount=1, $_vVal='')
	If $_iCount < 0 And $_vVal = '' Then Return SetError(1,0,0)
	Local $iIndexCtrl = __GraphCtrl_GetIndex($_iID)
	If $iIndexCtrl = -1 Then Return SetError(2,0,0)
	Local $aCtrl     = $__aGraphCtrl[$iIndexCtrl][1]
	Local $oCtrl     = $aCtrl[0]
	If $_vVal <> '' Then
		If IsArray($_vVal) Then
			Local $aPoints[UBound($_vVal)+1] = [UBound($_vVal)]
			For $i = 1 To $aPoints[0]
				$aPoints[$i] = $oCtrl.Item('H') - $_vVal[$i -1]
			Next
		Else
			Local $aPos = StringSplit($_vVal, ','), $aPoints[$aPos[0]+1] = [$aPos[0]]
			For $i = 1 To $aPos[0]
				$aPoints[$aPos[0] +1 -$i] = $oCtrl.Item('H') - $aPos[$i]
			Next
		EndIf
	Else
		If $_iCount = 0 Then
			Local $aPoints[1] = [0]
		Else
			Local $iStep = Int( $oCtrl.Item('H') / ($_iCount +1))
			Local $aPoints[$_iCount +2] = [$_iCount +1]
			For $i = 1 To $_iCount
				$aPoints[$_iCount +1 -$i] =  $oCtrl.Item('H') - ($i * $iStep)
			Next
		EndIf
	EndIf
	$aCtrl[2] = $aPoints
	$__aGraphCtrl[$iIndexCtrl][1] = $aCtrl
EndFunc  ;==_GraphCtrl_SetHelpline

;===============================================================================
; Function Name....: _GraphCtrl_Draw
; Description......: Draw the graph with parameters from creation by passed value.
; .................: Draws value by value from left to right and starts again from left if end is reached.
; .................: Older values will overwritten.
; Parameter(s).....: $_iID          Control ID, you've gotten from _GraphCtrl_Create
; .................: $_iVal         Current value to draw
; Return Value(s)..: Nothing
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _GraphCtrl_Draw($_iID, $_iVal)
	Local $iIndexCtrl = __GraphCtrl_GetIndex($_iID)
	Local $oBuffer    = __GetBuffer($__aGraphCtrl[$iIndexCtrl][2])
	Local $aCtrl      = $__aGraphCtrl[$iIndexCtrl][1]
	Local $aVScale    = $__aGraphCtrl[$iIndexCtrl][3]
	Local $aHScale    = $__aGraphCtrl[$iIndexCtrl][4]
	Local $oCtrl      = $aCtrl[0]
	Local $aCoord     = $aCtrl[1]
	Local $aHelpLine  = $aCtrl[2]
	Local $n          = $oCtrl.Item('CoordIndex')
	Local $iStamp     = $oCtrl.Item('TimeStamp')
	If $iStamp = 0 Or _Timer_Diff($iStamp) >= $oCtrl.Item('Intervall') Then
		$oCtrl.Item('TimeStamp') = _Timer_Init()
		_GDIPlus_GraphicsFillRect($oBuffer.Item('Context'), 0, 0, $oCtrl.Item('W'), $oCtrl.Item('H'), $oCtrl.Item('BrushBG'))                                       ; ==  Background
		If $aHelpLine[0] > 0 Then
			For $i = 1 To $aHelpLine[0]
				_GDIPlus_GraphicsDrawLine($oBuffer.Item('Context'), 0, $aHelpLine[$i], $oCtrl.Item('W'), $aHelpLine[$i], $oCtrl.Item('PenHelp'))                    ; == Help lines
			Next
		EndIf
		If $aVScale[0] > 0 Then                                                                                                                                     ; == vert. scaling
			For $i = 1 To $aVScale[0]
				_GDIPlus_GraphicsDrawLine($oBuffer.Item('Context'), 0, $oCtrl.Item('H') -$aVScale[$i], 5, $oCtrl.Item('H') -$aVScale[$i], $oCtrl.Item('PenAxes'))
			Next
		EndIf
		If $aHScale[0] > 0 Then                                                                                                                                     ; == horiz. scaling
			For $i = 1 To $aHScale[0]
				_GDIPlus_GraphicsDrawLine($oBuffer.Item('Context'), $aHScale[$i], $oCtrl.Item('H'), $aHScale[$i], $oCtrl.Item('H') -5, $oCtrl.Item('PenAxes'))
			Next
		EndIf

		$aCoord[$n][0] = $n / $oCtrl.Item('Density')
		$aCoord[$n][1] = $_iVal
		_GDIPlus_GraphicsDrawLines($oBuffer.Item('Context'), $aCoord, $oCtrl.Item('PenGraph'))                                                                      ; == Graph
		_GDIPlus_GraphicsDrawLine ($oBuffer.Item('Context'), $aCoord[$n][0] -1, 0               , $aCoord[$n][0]  , $oCtrl.Item('H'), $oCtrl.Item('PenPredraw'))    ; == Pre drawed line
		_GDIPlus_GraphicsDrawLine ($oBuffer.Item('Context'), 0                , $oCtrl.Item('H'), $oCtrl.Item('W'), $oCtrl.Item('H'), $oCtrl.Item('PenAxes'))       ; == X-Axis
		_GDIPlus_GraphicsDrawLine ($oBuffer.Item('Context'), 0                , 0               , 0               , $oCtrl.Item('H'), $oCtrl.Item('PenAxes'))       ; == Y-Axis

		_GDIPlus_GraphicsDrawImage($oBuffer.Item('Graphics'), $oBuffer.Item('Bitmap'), $oCtrl.Item('X'), $oCtrl.Item('Y'))                                          ; == Backbuffer

		$n += 1
		Select
			Case $n < $oCtrl.Item('UB') And  $oCtrl.Item('First')
				$aCoord[0][0] = $n
			Case $n = $oCtrl.Item('UB')
				$n = 1
				If $oCtrl.Item('First') Then $oCtrl.Item('First') = False
		EndSelect
		$oCtrl.Item('CoordIndex') = $n

		$aCtrl[0] = $oCtrl
		$aCtrl[1] = $aCoord
		$aCtrl[2] = $aHelpLine
		$__aGraphCtrl[$iIndexCtrl][1] = $aCtrl
	EndIf
EndFunc  ;==>_GraphCtrl_Draw



#region - Internal Functions


Func __GraphCtrl_Startup()
	$__MOUSEPROC_ACTIVE = 1
	If $ghGDIPDll = 0 Then _GDIPlus_Startup()
	$__hSTUB__MouseProcGraph = DllCallbackRegister("__MouseProcGraph", "long", "int;wparam;lparam")
	$__hMOD_GRAPH = _WinAPI_GetModuleHandle(0)
	$__hHOOK_MOUSE_GRAPH = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($__hSTUB__MouseProcGraph), $__hMOD_GRAPH)
EndFunc

Func _GDIPlus_GraphicsDrawLines($hGraphics, $aPoints, $hPen)  ; == by UEZ
	Local $iI, $iCount, $pPoints, $tPoints, $aResult

	$iCount = $aPoints[0][0]
	$tPoints = DllStructCreate("float[" & $iCount * 2 & "]")
	$pPoints = DllStructGetPtr($tPoints)
	For $iI = 1 To $iCount
		DllStructSetData($tPoints, 1, $aPoints[$iI][0], (($iI - 1) * 2) + 1)
		DllStructSetData($tPoints, 1, $aPoints[$iI][1], (($iI - 1) * 2) + 2)
	Next
	$aResult = DllCall($ghGDIPDll, "uint", "GdipDrawLines", "handle", $hGraphics, "handle", $hPen, "ptr", $pPoints, "int", $iCount)
	Return 1
EndFunc   ;==>_GDIPlus_GraphicsDrawLines

Func __GraphCtrlDispose()
	_WinAPI_UnhookWindowsHookEx($__hHOOK_MOUSE_GRAPH)
	DllCallbackFree($__hSTUB__MouseProcGraph)
	If $ghGDIPDll = 0 Then Return
	; == Dispose by Ctrl
	Local $aTmp, $oTmp
	For $i = 1 To $__aGraphCtrl[0][0]
		$aTmp = $__aGraphCtrl[$i][1]
		$oTmp = $aTmp[0]
		_GDIPlus_BrushDispose($oTmp.Item('BrushBG'))
		_GDIPlus_PenDispose  ($oTmp.Item('PenGraph'))
		_GDIPlus_PenDispose  ($oTmp.Item('PenPredraw'))
		_GDIPlus_PenDispose  ($oTmp.Item('PenAxes'))
	Next
	; == Dispose by Buffer
	For $i = 1 To $__aDC[0][0]
		$oTmp = $__aDC[$i][1]
		_GDIPlus_BitmapDispose  ($oTmp.Item('Bitmap'))
		_GDIPlus_GraphicsDispose($oTmp.Item('Graphics'))
		_GDIPlus_GraphicsDispose($oTmp.Item('Context'))
	Next
	_GDIPlus_Shutdown()
EndFunc  ;==>__GraphCtrlDispose

Func __ObjBufferRegister($_hGui)
	If $__aDC[0][0] > 0 Then
		For $i = 1 To $__aDC[0][0]
			If $__aDC[$i][0] = $_hGui Then Return
		Next
	EndIf
	Local $oBuffer = ObjCreate('Scripting.Dictionary')
	__GraphCreateBuffer($_hGui, $oBuffer)
	$__aDC[0][0] += 1
	ReDim $__aDC[$__aDC[0][0] +1][2]
	$__aDC[$__aDC[0][0]][0] = $_hGui
	$__aDC[$__aDC[0][0]][1] = $oBuffer
EndFunc  ;==>__ObjBufferRegister

Func __GetBuffer($_hGui)
	For $i = 1 To $__aDC[0][0]
		If $__aDC[$i][0] = $_hGui Then Return $__aDC[$i][1]
	Next
	Return SetError(1,0,0)
EndFunc  ;==>__GetBuffer

Func __GraphCreateBuffer($_hGui, ByRef $_oBuffer)
	Local $iW, $iH
	$iW = _WinAPI_GetClientWidth($_hGui)
	$iH = _WinAPI_GetClientHeight($_hGui)
	$_oBuffer.Add('Graphics', _GDIPlus_GraphicsCreateFromHWND($_hGui))
	$_oBuffer.Add('Bitmap'  , _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $_oBuffer.Item('Graphics')))
	$_oBuffer.Add('Context' , _GDIPlus_ImageGetGraphicsContext($_oBuffer.Item('Bitmap')))
	_GDIPlus_GraphicsSetSmoothingMode($_oBuffer.Item('Context'), 2)
EndFunc  ;==>__GraphCreateBuffer

Func __GraphCtrl_GetIndex($_iID)
	For $i = 1 To $__aGraphCtrl[0][0]
		If $__aGraphCtrl[$i][0] = $_iID Then Return $i
	Next
	Return -1
EndFunc  ;==>__GraphCtrl_GetIndex

Func __MouseProcGraph($nCode, $wParam, $lParam)
	If $nCode <> $__HC_ACTION Then Return _WinAPI_CallNextHookEx($__hHOOK_MOUSE_GRAPH, $nCode, $wParam, $lParam)
	Local $iX, $iY, $hGui, $aCtrl, $oCtrl, $tRect, $iTop, $iLeft
	Local $tMSLLHOOKSTRUCT = DllStructCreate("int X;int Y;dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo", $lParam)
	Local $tPoint = DllStructCreate('int;int')
	$iX = DllStructGetData($tMSLLHOOKSTRUCT, 1)
    $iY = DllStructGetData($tMSLLHOOKSTRUCT, 2)
	DllStructSetData($tPoint, 1, $iX)
	DllStructSetData($tPoint, 2, $iY)

	Switch $wParam
		Case $WM_LBUTTONDOWN, $WM_LBUTTONUP, $WM_RBUTTONDOWN, $WM_RBUTTONUP, $WM_MBUTTONDOWN, $WM_MBUTTONUP
			For $i = 1 To $__aGraphCtrl[0][0]
				$hGui = $__aGraphCtrl[$i][2]
				If Not WinActive($hGui) Then ContinueLoop
				$tRect = _WinAPI_GetWindowRect($hGui)
				If _WinAPI_PtInRect($tRect, $tPoint) Then
					$aCtrl = $__aGraphCtrl[$i][1]
					$oCtrl = $aCtrl[0]
					_SystemGetWindowBorder($iTop, $iLeft)
					Local $x1 = DllStructGetData($tRect,1) +$iLeft +$oCtrl.Item('X')
					Local $x2 = $x1 +$oCtrl.Item('W')
					Local $y1 = DllStructGetData($tRect,2) +$iTop +$oCtrl.Item('Y')
					Local $y2 = $y1 +$oCtrl.Item('H')
					DllCall("user32", 'long', 'SetRect', 'ptr', DllStructGetPtr($tRect), 'long', $x1, 'long', $y1, 'long', $x2, 'long', $y2)
					If _WinAPI_PtInRect($tRect, $tPoint) Then
						GUICtrlSendToDummy($__aGraphCtrl[$i][0], $wParam)
						ExitLoop
					EndIf
				EndIf
			Next
	EndSwitch

	Return _WinAPI_CallNextHookEx($__hHOOK_MOUSE_GRAPH, $nCode, $wParam, $lParam)
EndFunc  ;==>__MouseProcGraph

;===============================================================================
; Function Name....: __SystemGetWindowBorder
; Description......: Calculates side and top border of window
; Author(s)........: BugFix ( bugfix@autoit.de )
;===============================================================================
Func _SystemGetWindowBorder(ByRef $_iTopBorder, ByRef $_iSideBorder)
	Local Const $SM_CYCAPTION = 4, $SM_CYEDGE = 46, $SM_CYBORDER = 6, $SM_CXBORDER = 5, $SM_CXEDGE = 45
	Local $aMetrics[5][2] = [[$SM_CYCAPTION], [$SM_CYEDGE], [$SM_CYBORDER], [$SM_CXBORDER], [$SM_CXEDGE]]
	Local $dll = DllOpen("user32.dll"), $aRet
	For $i = 0 To 4
		$aRet = DllCall($dll, "int", "GetSystemMetrics", "int", $aMetrics[$i][0])
		If IsArray($aRet) Then $aMetrics[$i][1] = $aRet[0]
	Next
	DllClose($dll)
	$_iTopBorder  = $aMetrics[0][1] + $aMetrics[1][1] + $aMetrics[2][1]
	$_iSideBorder = $aMetrics[3][1] + $aMetrics[4][1]
EndFunc  ;==>__SystemGetWindowBorder

#endregion


