Neues Control: Living Graph

    • Offizieller Beitrag

    Dieses GDIPlus basierte Control erlaubt die zeitliche grafische Darstellung von Werten.
    Beim Erstellen wird eine ID zurückgegeben, die wie üblich mit GuiGetMsg oder GuiCtrlSetOnEvent genutzt werden kann.

    Relevante Parameter sind:
    • Koordinaten auf der GUI, Breite und Höhe des Controls
    • Epochendauer in Sekunden (Zeit für einen kompletten Durchlauf des Controls), unterhalb 10 s ist dieser Wert jedoch nicht genau erreichbar
    • Darstellungsdichte (auf wieviel Pixel wird ein Wert abgebildet)
    • Farben der einzelnen Controlelemente

    Verfügbare Funktionen und Events:
    _GraphCtrl_Create
    Erstellen des Controls
    _GraphCtrl_VScaleSet
    Vertikale Skalierung od. deaktivieren
    _GraphCtrl_HScaleSet
    Horizontale Skalierung od. deaktivieren
    _GraphCtrl_SetColor
    Farben ändern für einzelnes Control-Element
    _GraphCtrl_SetDensity
    Darstellungsdichte ändern
    _GraphCtrl_SetHelpline
    Hilfslinien setzen od. deaktivieren

    Mit Mausklick (links, mitte, rechts) auf das Control sind mit GuiCtrlRead(ID) folgende Ereignisse auswertbar:
    • $WM_LBUTTONDOWN
    • $WM_LBUTTONUP
    • $WM_RBUTTONDOWN
    • $WM_RBUTTONUP
    • $WM_MBUTTONDOWN
    • $WM_MBUTTONUP

    LivingGraph v0.2
    [autoit]

    #Region - TimeStamp
    ; 2012-08-20 01:01:16 v 0.2
    #EndRegion - TimeStamp

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

    #cs

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

    - Grafische Darstellung eines sich ändernden (Meß)Wertes
    - "Aktualisierungsfenster" läuft von links nach rechts über den Darstellungsbereich und überschreibt alte Werte mit den neuen

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

    Funktionsübersicht:
    _GraphCtrl_Create
    _GraphCtrl_VScaleSet
    _GraphCtrl_HScaleSet
    _GraphCtrl_SetColor
    _GraphCtrl_SetDensity
    _GraphCtrl_SetHelpline

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

    Events:
    ID ist mit GuiGetMsg oder GuiCtrlSetOnEvent zu verwenden.
    Mit GuiCtrlRead(ID) sind folgende Ereignisse auswertbar:

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

    $WM_LBUTTONDOWN
    $WM_LBUTTONUP
    $WM_RBUTTONDOWN
    $WM_RBUTTONUP
    $WM_MBUTTONDOWN
    $WM_MBUTTONUP

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

    #ce

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

    #include-once
    #Include <GDIPlus.au3>
    #include <WinAPI.au3>
    #include <Timers.au3>
    #Include <WindowsConstants.au3>

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

    OnAutoItExitRegister('__GraphCtrlDispose')
    Global $__aDC[1][2] = [[0]] ; == Manage Buffers
    Global $__aGraphCtrl[1][5] = [[0]] ; == Manage Controls

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

    Global Const $__HC_ACTION = 0
    Global $__MOUSEPROC_ACTIVE = 0
    Global $__hSTUB__MouseProcGraph, $__hMOD_GRAPH, $__hHOOK_MOUSE_GRAPH
    Global $__iTop, $__iLeft
    _SystemGetWindowBorder($__iTop, $__iLeft)

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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)

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

    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

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    ;===============================================================================
    ; 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 ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    $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

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

    _GDIPlus_GraphicsDrawImage($oBuffer.Item('Graphics'), $oBuffer.Item('Bitmap'), $oCtrl.Item('X'), $oCtrl.Item('Y')) ; == Backbuffer

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

    $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

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

    $aCtrl[0] = $oCtrl
    $aCtrl[1] = $aCoord
    $aCtrl[2] = $aHelpLine
    $__aGraphCtrl[$iIndexCtrl][1] = $aCtrl
    EndIf
    EndFunc ;==>_GraphCtrl_Draw

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

    #region - Internal Functions

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

    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

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

    Func _GDIPlus_GraphicsDrawLines($hGraphics, $aPoints, $hPen) ; == by UEZ
    Local $iI, $iCount, $pPoints, $tPoints, $aResult

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

    $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

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

    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

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

    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

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

    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

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

    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

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

    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

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

    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)

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

    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

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

    Return _WinAPI_CallNextHookEx($__hHOOK_MOUSE_GRAPH, $nCode, $wParam, $lParam)
    EndFunc ;==>__MouseProcGraph

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

    ;===============================================================================
    ; Function Name....: __SystemGetWindowBorder
    ; Description......: Calculates side and top border of window
    ; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    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

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

    #endregion

    [/autoit]
    Bsp.
    [autoit]

    #Region - TimeStamp
    ; 2012-08-20 01:03:19 v 0.2
    #EndRegion - TimeStamp

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

    #include 'LivingGraph.au3'

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

    Opt("GUIOnEventMode", 1)

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

    Global $Gui = GUICreate('Test', 800, 400)
    GUISetBkColor(0x000000)
    GUISetOnEvent(-3, "_Exit")
    GUISetState()

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

    ; == Controls erstellen
    $iCtrlID1 = _GraphCtrl_Create($Gui, 20, 20, 760, 170, 20, -1, 1, 0xFFFFFFFF, 0xFF0000FF, 0xFFFF0000, 0xFF000000, 0xFFE0E0E0) ; == 20 s Epochendauer
    GUICtrlSetOnEvent($iCtrlID1, '_GraphEvent')
    ; == 10 s Epochendauer:
    $iCtrlID2 = _GraphCtrl_Create($Gui, 20, 210, 760, 170, 10)
    GUICtrlSetOnEvent($iCtrlID2, '_GraphEvent')

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

    ; == Hilfslinien erstellen
    _GraphCtrl_SetHelpline($iCtrlID1, -1, '54,108') ; == Position über X-Achse
    ; == alternativ mit Arrayübergabe
    Local $aHelp[6] = [25,50,75,100,125,150]
    _GraphCtrl_SetHelpline($iCtrlID2, -1, $aHelp)
    ; == oder per Angabe Anzahl Linien (zählen ohne abschließende Hilfslinie an der Control-Oberseite)
    ;~ _GraphCtrl_SetHelpline($iCtrlID1, 2)

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

    ; == Skalierung
    _GraphCtrl_VScaleSet($iCtrlID1) ; == vertikal, standardmäßig in 10%-Schritten
    ; == alternativ mit Wertangabe (Pixel ab X-Achse) über String oder Array
    _GraphCtrl_VScaleSet($iCtrlID2, 1, '85,170')
    ;~ Local $aV[2] = [85,170]
    ;~ _GraphCtrl_VScaleSet($iCtrlID1, 1, $aV)

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

    _GraphCtrl_HScaleSet($iCtrlID1) ; == horizontal, standarmäßig in Sekundenabstand
    _GraphCtrl_HScaleSet($iCtrlID2)

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

    $timer = TimerInit()
    $done = 0
    $iVal = 85
    $iVal1 = 50
    Do
    $iRnd = Random(-2,2,1)
    While $iVal +($iRnd) > 170 Or $iVal +($iRnd) < 0
    $iRnd = Random(-2,2,1)
    WEnd
    $iVal += ($iRnd)
    _GraphCtrl_Draw($iCtrlID1, $iVal)
    $iRnd = Random(-2,2,1)
    While $iVal1 +($iRnd) > 170 Or $iVal1 +($iRnd) < 0
    $iRnd = Random(-2,2,1)
    WEnd
    $iVal1 += ($iRnd)
    _GraphCtrl_Draw($iCtrlID2, $iVal1)
    If TimerDiff($timer) >= 3000 And $done = 0 Then
    $done = 1
    _GraphCtrl_HScaleSet($iCtrlID1, 0) ; == Skalierung deaktivieren
    _GraphCtrl_VScaleSet($iCtrlID1, 0)

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

    _GraphCtrl_SetHelpline($iCtrlID2, 0) ; == Helpline deaktivieren
    EndIf
    Sleep(5)
    Until False

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

    Func _Exit()
    Exit
    EndFunc

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

    Func _GraphEvent()
    Local $sCtrl = '$iCtrlID1'
    If @GUI_CtrlId = $iCtrlID2 Then $sCtrl = '$iCtrlID2'
    Switch GUICtrlRead(@GUI_CtrlId)
    Case $WM_LBUTTONDOWN
    ConsoleWrite($sCtrl & ' $WM_LBUTTONDOWN' & @CRLF)
    Case $WM_LBUTTONUP
    ConsoleWrite($sCtrl & ' $WM_LBUTTONUP' & @CRLF)
    Case $WM_RBUTTONDOWN
    ConsoleWrite($sCtrl & ' $WM_RBUTTONDOWN' & @CRLF)
    Case $WM_RBUTTONUP
    ConsoleWrite($sCtrl & ' $WM_RBUTTONUP' & @CRLF)
    Case $WM_MBUTTONDOWN
    ConsoleWrite($sCtrl & ' $WM_MBUTTONDOWN' & @CRLF)
    Case $WM_MBUTTONUP
    ConsoleWrite($sCtrl & ' $WM_MBUTTONUP' & @CRLF)
    EndSwitch
    EndFunc

    [/autoit]

    Danke an UEZ für die Funktion "_GDIPlus_GraphicsDrawLines" und die Beseitigung einer Unklarheiten. ;)

    • Offizieller Beitrag

    Hi, hab versucht das Beispiel auszuführen.
    Geht aber nicht.

    Zitat von SciTe

    C:\Program Files (x86)\AutoIt3\SciTE\LivingGraph.au3 (463) : ==> The requested action with this object has failed.:
    $_oBuffer.Add('Graphics', _GDIPlus_GraphicsCreateFromHWND($_hGui))
    $_oBuffer.Add('Graphics', _GDIPlus_GraphicsCreateFromHWND($_hGui))^ ERROR
    ->01:26:56 AutoIT3.exe ended.rc:1



    Edit: Lag an der Autoitversion, hab auf dem Schlepptop noch 3.3.6.1, damit läuft das Script nicht.

    Das Control sieht gut aus, mal sehen ob ich es mal gebrauchen kann :thumbup:

  • Schön gemacht. Eine (deutlich größere) Variante mit Graphics gibt es im engl. Forum. Wenn bei dir noch ein paar Funktionen dazukommen, wäre ein Umschwung natürlich denkbar. Aber sonst Klasse :thumbup:

    • Offizieller Beitrag

    Raupi
    Keine Ahnung, wie du den Fehler produzierst.

    Wenn das Control erstellt wird, passiert folgendes:
    - wenn GDI nicht gestartet, wird es gestartet
    - es wird geprüft, ob für die angegebene GUI bereits ein Buffer erstellt wurde, wenn nicht wird dieser erstellt
    Das passiert hier:

    [autoit]

    Local $oBuffer = ObjCreate('Scripting.Dictionary')
    __GraphCreateBuffer($_hGui, $oBuffer) ; <== $oBuffer wird ByRef übergeben und dann befüllt

    [/autoit]

    Beim 'Befüllen' tritt bei dir der Fehler auf.
    Das ist aber eigentlich schlichtweg unmöglich, mir ist kein Zustand bekannt, indem einem Dictionary kein Wert zugewiesen werden kann, wenn der Schlüssel valid ist. Werte können Handle sein - nur als Schlüssel lassen sie sich nicht verwenden.
    Also: es ist sachlich alles richtig, aber dein AutoIt sieht das wohl anders... :whistling:

    • Offizieller Beitrag

    Der King des Array's erweitert sein Königreich ;) Gefällt mir sehr gut, kann dies praktischer Weise gerade auch sehr gut gebrauchen. Die Perfomance ist schon ziemlich super, aber hat jemand ne Idee wie man es eventuell noch schneller bekommen könnte? Wahrscheinlich nicht mit den GDI Befehlen von AutoIt, die haben ja so ihre Limits. Problem ist allerdings, dass ich versuche 8 Bars gleichzeitig auf einem relativ alten XP Rechner sehr schnell darzustellen (>30fps), bei keinem Sleep siehts zwar perfekt aus, das aber auch mit 100%iger Prozessorlast, bei 5ms (bzw 10) habe ich auf dem PC um die 20%.

    Wäre super wenn jemand ne Idee hat, ist aber auch nicht so dringen. Was ich eigentlich nur sagen wollte: Bin begeistert BugFix :) Saubere Arbeit, schön gescripted und sehr Anwendungstauglich - so wie man es von dir gewohnt ist!

    Gruß
    Spider

    • Offizieller Beitrag

    BugFix , der Fehler tritt bei Autoit 3.3.6.1 auf,die Version scheint verbungt zu sein.
    Habe es unter Beta 3.3.7.14 auch getestet, da läuft es einwandfrei.

    Auf dem Schlepptop hab ich leider keine anderen Versionen, bin auch jetzt zu Faul aufzustehen und einen andern Rechner hochzufahren. :rolleyes:

  • Super :thumbup:
    Allerdings fällt mir etwas beim Beispielscript auf: Nach ein paar Sekunden verschwinden im oberen Graph die kleinen Striche unten und an der Seite und im unteren Graph die langen waagerechten Striche:
    Vorher:
    [Blockierte Grafik: http://s14.directupload.net/images/120820/dvzrw77q.jpg]


    Nachher
    [Blockierte Grafik: http://s7.directupload.net/images/120820/hweqp6fe.jpg]

  • @Dieter: Hast du dir das Beispiel-Skript mal angeschaut? Das wird absichtilich nach 3 Sekunden gemacht um diese Funktionalität zu zeigen.

    BugFix : Ich hätte da einen Bug zum fixen ;):
    Wenn man beim erstem Control die Strichstärke auf 2 oder mehr erhöht, dann sieht man auch beim zweiten Control eine Veränderung.
    Außerdem wollte ich fragen wofür man denn die Density braucht? Kann man die nicht aus Größe des Controls und Laufzeit (EpochTime) errechnen?

  • Das Ganze UDF tauglich zu machen, ist schon klasse! Zumal man "um die Ecke" denken muss. Ich bin eher der Anti UDF Typ.

    Sauber programmiert! :thumbup:

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    • Offizieller Beitrag

    Eine (deutlich größere) Variante mit Graphics gibt es im engl. Forum.

    Kannst du mal den Link posten? Habe bei meiner Suche nichts entdeckt, bin mir aber auch nicht sicher unter welchen Begriffen Vergleichbares dort gepostet sein könnte.

    Der King des Array's erweitert sein Königreich

    Da gebührt der meiste Dank dem Lehrmeister UEZ :thumbup: . Ohne seine Beispiele und tatkräftige Hilfe hätte sich mir diese Thematik wohl nicht erschlossen.

    Wenn man beim erstem Control die Strichstärke auf 2 oder mehr erhöht, dann sieht man auch beim zweiten Control eine Veränderung.
    Außerdem wollte ich fragen wofür man denn die Density braucht? Kann man die nicht aus Größe des Controls und Laufzeit (EpochTime) errechnen?

    OK, das mit der Pinselstärke muss ich nochmal nachschauen.
    Zur Density: Ich hatte das aus einem Bsp. von UEZ nachgebaut und diesen Parameter übernommen. Muß ich tatsächlich nochmal unter die Lupe nehmen, inwiefern das erforderlich ist. War auch schon reichlich spät (oder früh ;)) als ich damit fertig wurde.

    Zumal man "um die Ecke" denken muss.

    Das ist wohl wahr :D. Aber wenn man es ein paar mal gemacht hat, kennt man die Fallstricke.
    Es gibt ja so einige Lösungen, die durchaus als einzelne Controls existiren könnten - wenn sie diese Basis-Funktionalität aufweisen würden:
    - ansprechbar über ID mit GuiGetMsg und GuiCtrlSetOnEvent
    - keine extra StartUps/ShutDowns und Nachrichtenverwaltung

    Auch die GDIPlus-UDF weist ja unnütze Funktionen auf. So ließen sich .._StartUp() und .._ShutDown() problemlos einsparen, indem man diese Funktionen ausschließlich intern nutzt und über die Kontrolle der (nicht)gestarteten GDIPlus Dll ..StartUp und bei AutoItExit ..ShutDown ausführt.
    Genau das habe ich hier im Control auch getan. ;)

    Ansonsten freut es mich natürlich, wenn ihr damit was anfangen könnt. Bei mir ist es eigentlich als "Abfall" in einem Projekt entstanden. Ich wollte die Lösung nicht nur projektbezogen und habe deshalb ein allein "lebensfähiges" Control erstellt.

  • Zitat von GTASpider

    Die Perfomance ist schon ziemlich super, aber hat jemand ne Idee wie man es eventuell noch schneller bekommen könnte? Wahrscheinlich nicht mit den GDI Befehlen von AutoIt, die haben ja so ihre Limits.

    Hab _DRAW() mal geprofiled. Zeiten in Millisekunden

    Wie man deutlich sieht, wird der Löwenanteil der Zeit von

    [autoit]

    _GDIPlus_GraphicsDrawImage($oBuffer.Item('Graphics'), $oBuffer.Item('Bitmap'), $oCtrl.Item('X'), $oCtrl.Item('Y'))

    [/autoit]

    verbraten, gefolgt von den Hilfslinien , der Rest innerhalb der Funktion ist zeitlich zu vernachlässigen.

    Ja, bei Verwendung von GDI+-Funktionen ist nicht mehr viel zu machen.....unabhängig von AutoIt!

  • Kannst du mal den Link posten? Habe bei meiner Suche nichts entdeckt, bin mir aber auch nicht sicher unter welchen Begriffen Vergleichbares dort gepostet sein könnte.

    Vermutlich ist das hier gemeint.

  • Klasse UDF! Danke!
    Eine Frage hab ich dazu - gibt es die einstellungsmöglichkeit den Graphen nach erreichen der rechten Seite weiter vor schieben zu lassen. Also das der Graph nicht die alten Werte überschreibt (- wieder von vorne anfängt), sondern nur nach links aus dem GUI schiebt?

    • Offizieller Beitrag

    Also das der Graph nicht die alten Werte überschreibt (- wieder von vorne anfängt), sondern nur nach links aus dem GUI schiebt?


    Das ist die Variante, ständig am rechten Control-Rand zu zeichnen. Machbar ist das sicher, muss allerdings die Verwaltung umgestellt werden. Vielleicht werde ich das noch einbauen. Im Moment habe ich aber viele andere Dinge um die Ohren.