Eigenes Control: RangeBar

    • Offizieller Beitrag

    Hi,
    vor ein paar Tagen tauchte im Forum die Frage nach einer Progressbar mit 2 Slidern auf.
    Ich fand den Gedanken gar nicht übel und da ich kein dementsprechendes Ctrl gefunden habe, ist nun dieses Projekt entstanden:
    Ein selbstgezeichnetes Ctrl zur Bereichsauswahl durch Verschieben der Unter- und/oder Obergrenze (Klicken, Ziehen).

    Hier der aktuelle Status:
    RangeBar-Control
    - Auswahl eines Werte-Bereiches durch Verschieben der Unter- und/oder Obergrenze (klicken-ziehen)
    - Funktionalität eines Sliders aber von zwei Seiten einstellbar
    - Optik einer Progressbar
    - einstellbar:
    Farbe gewählter Bereich (Range),
    Farbe ungenutzter Bereich (BackColor),
    Farbe Marker (Begrenzungen der Range),
    Farbe Ticks,
    Farbe Label
    - Ticks u. Label optional, Label enthalten zwangsweise Ticks
    - Setzen Anzahl Ticks (optional auch gleich Limit)
    - nach Anzahl Ticks autom. Berechnung der Labelwerte
    - Positionierung der Label mittig unter den Ticks nach tatsächlicher Schriftbreite
    - Formatierung der Label als Dezimaldarstellung (Standard) oder Stunden / Minuten Darstellung
    - Setzen Limit (unterster, oberster Wert)

    - Hinweis:
    Durch Pixelweises Verschieben der Range (um möglichst hohe Genauigkeit der Werte zu erreichen) kann nur relativ langsam
    die Bereichsgrenze gezogen werden. Man "rutscht" recht schnell ab.

    - In Planung:
    Verschieben der gesamten Range durch STRG+MouseMove
    Style für vertikale Anordnung des Ctrl
    Style für Ticks oberhalb der Bar
    Möglichkeit mehrere Ctrl gleichzeitig zu erstellen

    Spielt mal ein bischen damit und gebt euren Kommentar ab.

    Edit 24.05.2010
    - Das Mausverhalten ist jetzt etwas verbessert. Ich könnte damit leben.
    - Neuer Parameter: Transparenz
    - Bar, Ticks und Label werden in eigenen Buffer gezeichnet und nur was sich ändert, wird neu gezeichnet.
    - Funktion zur Ausgabe der tatsächlichen Control-Größe hinzugefügt (Je nach Style unterschiedlich). Rückgabe als Array mit Einzelwerten und RECT-Struktur.

    Spoiler anzeigen
    [autoit]

    #cs
    RangeBar-Control

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

    - Auswahl eines Werte-Bereiches durch Verschieben der Unter- und/oder Obergrenze (klicken-ziehen)
    - Funktionalität eines Sliders aber von zwei Seiten einstellbar
    - Optik einer Progressbar
    - einstellbar:
    Farbe gewählter Bereich (Range),
    Farbe ungenutzter Bereich (BackColor),
    Farbe Marker (Begrenzungen der Range),
    Farbe Ticks,
    Farbe Label
    - Ticks u. Label optional, Label enthalten zwangsweise Ticks
    - Setzen Anzahl Ticks (optional auch gleich Limit)
    - nach Anzahl Ticks autom. Berechnung der Labelwerte
    - Positionierung der Label mittig unter den Ticks nach tatsächlicher Schriftbreite
    - Formatierung der Label als Dezimaldarstellung (Standard) oder Stunden / Minuten Darstellung
    - Setzen Limit (unterster, oberster Wert)

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

    - Hinweis:
    Durch Pixelweises Verschieben der Range (um möglichst hohe Genauigkeit der Werte zu erreichen) kann nur relativ langsam
    die Bereichsgrenze gezogen werden. Man "rutscht" recht schnell ab.

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

    - In Planung:
    Verschieben der gesamten Range durch STRG+MouseMove
    Style für vertikale Anordnung des Ctrl
    Style für Ticks oberhalb der Bar
    Möglichkeit mehrere Ctrl gleichzeitig zu erstellen
    #ce

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

    #include-once
    #include <GDIPlus.au3>
    #include <WindowsConstants.au3>

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

    #region - RangeBar-Style
    Global Const $RBS_HORICONTAL = 0x1 ; Ctrl als horizontale Bar
    Global Const $RBS_VERTICAL = 0x2 ; noch nicht implementiert
    Global Const $RBS_TICKS_BELOW_LEFT = 0x4 ; Ticks (und Label falls gesetzt) unten oder bei VERTICAL links
    Global Const $RBS_TICKS_ONTOP_RIGHT = 0x8 ; Ticks (und Label falls gesetzt) oben oder bei VERTICAL rechts
    Global Const $RBS_LABEL = 0x10 ; Beschriftung der Ticks mit den Werten
    Global Const $RBS_BASE60 = 0x20 ; Verwendung bei Stunden- oder Minutendarstellung, formatiert auf [h]h:mm bzw. [m]m:ss
    Global Const $RBS_DEFAULT = BitOR($RBS_HORICONTAL,$RBS_TICKS_BELOW_LEFT)
    #endregion

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

    Global $tLeftMarker, $tRightMarker, $tRange, $bSetCursor = False ; <== zur Positionskontrolle Maus über Marker/Range
    Global $bIsActive = False, $aCheck[4] = [-1,-1,-1,-1] ; <== Kontrolle GUI aktiv/wird bewegt wg. Neuzeichnen Ctrl
    Global $Dll_user32 = DllOpen("user32")

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

    Global $guiRange = GUICreate('Bereichsauswahl [Ober- /Untergrenze]')
    Global $RangeCtrl = _GDIPlus_RangeBar_Create($guiRange, 20, 10, 300, 17, BitOR($RBS_DEFAULT,$RBS_LABEL,$RBS_BASE60)) ; <== Variablennamen für Ctrl in _WM_MOVE u. __WinStateCheck ggf. anpassen
    GUICtrlCreateLabel('von bis', 90, 105)
    GUICtrlCreateLabel('%', 65, 123)
    GUICtrlCreateLabel('Wert', 50, 153)
    Global $inLeftpercent = GUICtrlCreateInput('', 80, 120, 40, 20)
    Global $inRightpercent = GUICtrlCreateInput('', 140, 120, 40, 20)
    Global $inLeftvalue = GUICtrlCreateInput('', 80, 150, 40, 20)
    Global $inRightvalue = GUICtrlCreateInput('', 140, 150, 40, 20)
    GUICtrlCreateLabel('=',187, 153)
    Global $inValue = GUICtrlCreateInput('', 200, 150, 40, 20)
    GUISetState()

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

    AdlibRegister('__WinStateCheck', 100)
    GUIRegisterMsg($WM_MOUSEMOVE, '_WM_MOUSEMOVE')

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

    $aSize = _GDIPlus_RangeBar_GetSize($RangeCtrl)
    ConsoleWrite('Controlgröße:' & @CRLF & _
    'x: ' & $aSize[0] & @CRLF & _
    'y: ' & $aSize[1] & @CRLF & _
    'w: ' & $aSize[2] & @CRLF & _
    'h: ' & $aSize[3] & @CRLF)

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

    ; === Range neu setzen
    _GDIPlus_RangeBar_SetRange($RangeCtrl, 20, 50)

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

    ; === Tick-Anzahl und Limit setzen
    _GDIPlus_RangeBar_SetTickLimit($RangeCtrl, 6, '6 18')

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

    Do
    Until GUIGetMsg() = -3
    _GDIPlus_RangeBar_Dispose($RangeCtrl)

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

    ; =================================================================================================
    ; Range-Ctrl erstellen
    ; Rückgabe Strukturvariable zur Verwendung in den Einzelfunktionen
    ; Parameter: $hWnd - Handle der GUI, in der das Ctrl erstellt wird
    ; $x - X-Position der Bar des Ctrl, Zeichnungsfläche beginnt bei $x-20 !!
    ; $y - Y-Position der Bar des Ctrl
    ; $width - Breite der Bar des Ctrl, Zeichnungsbreite = 20+$width+20
    ; $height - Höhe der Bar des Ctrl, Zeichnungshöhe (inkl. Platz f. Ticks u. Label) = $height+40
    ; $iStyle - -1 od. Default für $RBS_DEFAULT, Details s. Konstantendeklaration
    ; $bGDIstart - wenn GDI noch nicht initialisiert wurde = True (Standard)
    ; $iRangeColor - Farbe für den gewählten Bereich, -1 od. Default für 0x0000FF
    ; $iBackColor - Farbe für den ungentzten Bereich, -1 od. Default für 0x696969
    ; $iMarkerColor - Farbe der Bereichsbegrenzer, -1 od. Default für 0xFFFFFF
    ; $iTickColor - Farbe der Skalierung (Ticks), -1 od. Default für 0xA9A9A9
    ; $iLabelColor - Farbe der Tickbeschriftung, -1 od. Default für 0xB22222
    ; $iTrans - Transparenz 0 - 255, Standard: 255 = keine Transparenz
    ; =================================================================================================
    Func _GDIPlus_RangeBar_Create($hWnd, $x, $y, $width, $height = 17, $iStyle = -1, $bGDIstart = True, $iRangeColor = 0x0000FF, _
    $iBackColor = 0x696969, $iMarkerColor = 0xFFFFFF, $iTickColor = 0xA9A9A9, $iLabelColor = 0xB22222, $iTrans=255) ; Range-Ctrl erstellen
    If $iStyle = -1 Or IsKeyword($iStyle) Then $iStyle = $RBS_DEFAULT
    If $bGDIstart = -1 Or IsKeyword($bGDIstart) Then $bGDIstart = True
    If $iRangeColor = -1 Or IsKeyword($iRangeColor) Then $iRangeColor = 0x0000FF
    If $iBackColor = -1 Or IsKeyword($iBackColor) Then $iBackColor = 0x696969
    If $iMarkerColor = -1 Or IsKeyword($iMarkerColor) Then $iMarkerColor = 0xFFFFFF
    If $iTickColor = -1 Or IsKeyword($iTickColor) Then $iTickColor = 0xA9A9A9
    If $iLabelColor = -1 Or IsKeyword($iLabelColor) Then $iLabelColor = 0xB22222
    Local $hGraphic, $hBrushRange, $hBrushBack, $hPenMarker, $hPenTicks
    Local $hFormat, $hFamily, $hFont, $hBrushFont, $hBitmapBar, $hBitmapTicks, $hBitmapLabel, $tLayout, $aInfo, $chrX
    Local $hImageBar, $hImageTicks, $hImageLabel, $aCtrlSize[4] = [$x,$y,$width,$height]
    Local $sRangeColor = '0x' & Hex($iTrans, 2) & Hex($iRangeColor, 6)
    Local $sBackColor = '0x' & Hex($iTrans, 2) & Hex($iBackColor, 6)
    Local $sMarkerColor = '0x' & Hex($iTrans, 2) & Hex($iMarkerColor, 6)
    Local $sTickColor = '0x' & Hex($iTrans, 2) & Hex($iTickColor, 6)
    Local $sLabelColor = '0x' & Hex($iTrans, 2) & Hex($iLabelColor, 6)
    Local $xLMark = 0, $xRMark = 100 ; Marker links und rechts
    Local $tRangeCtrl = DllStructCreate( _ ; Struktur zur Aufnahme aller Ctrl-Infos
    "int Style;" & _ ; Ctrl Style
    "hwnd Graphics;" & _ ; Graphics Handle
    "hwnd BrushRange;" & _ ; Brush Range Handle
    "hwnd BrushBack;" & _ ; Brush Hintergrund Handle
    "hwnd PenMarker;" & _ ; Pen Marker Handle
    "hwnd PenTicks;" & _ ; Pen Tick Handle
    "hwnd Format;" & _ ; Stringformat Handle
    "hwnd Family;" & _ ; FontFamily Handle
    "hwnd Font;" & _ ; Font Handle
    "hwnd BrushFont;" & _ ; Brush Font Handle
    "hwnd Bitmap[3];" & _ ; für Buffer [Bar,Ticks,Label]
    "hwnd Image[3];" & _ ; für Buffer [Bar,Ticks,Label]
    "int RECTBar[4];" & _ ; Koordinaten Bar [$x,$y,$width,$height]
    "int RECTCtrl[4];" & _ ; Koordinaten ges. Ctrl inkl. Ticks/Label (sofern gesetzt) [L,T,R,B]
    "int Marker[2];" & _ ; X-Koordinaten Marker [links,rechts] px relativ zur Bar
    "int Ticks;" & _ ; Anzahl Markierungen (Minimum Anfang u. Ende - automatisch)
    "char Label[128];" & _ ; Beschriftung unter den Ticks (Limit, Skalierung)
    "int RECTleft[4];" & _ ; RECT linker Marker [L,T,R,B]
    "int RECTright[4];") ; RECT rechter Marker [L,T,R,B]
    If $bGDIstart Then _GDIPlus_Startup() ; Initialize GDI+ library
    $hFormat = _GDIPlus_StringFormatCreate(0) ; Create string format object
    $hFamily = _GDIPlus_FontFamilyCreate("Arial") ; Create font family
    $hFont = _GDIPlus_FontCreate($hFamily, 8) ; Create font
    $hBrushRange = _GDIPlus_BrushCreateSolid($sRangeColor) ; Create brush used range
    $hBrushBack = _GDIPlus_BrushCreateSolid($sBackColor) ; Create brush unused range
    $hPenMarker = _GDIPlus_PenCreate($sMarkerColor) ; Create pen marker
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) ; Create graphics object
    $hBitmapBar = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic) ; Create bmp Bar
    $hImageBar = _GDIPlus_ImageGetGraphicsContext($hBitmapBar) ; Create buffer Bar
    _GDIPlus_GraphicsSetSmoothingMode($hImageBar, 4)
    Select
    Case BitAND($iStyle, $RBS_LABEL)
    $hPenTicks = _GDIPlus_PenCreate($sTickColor) ; Create pen ticks
    $hBitmapTicks = _GDIPlus_BitmapCreateFromGraphics($width, 6, $hGraphic) ; Create bitmap ticks
    $hImageTicks = _GDIPlus_ImageGetGraphicsContext($hBitmapTicks) ; Create buffer ticks
    $hBrushFont = _GDIPlus_BrushCreateSolid($sLabelColor) ; Create brush label
    $hBitmapLabel = _GDIPlus_BitmapCreateFromGraphics($width +40, 12, $hGraphic) ; Create bmp label
    $hImageLabel = _GDIPlus_ImageGetGraphicsContext($hBitmapLabel) ; Create buffer label
    _GDIPlus_GraphicsSetSmoothingMode($hImageTicks, 4)
    _GDIPlus_GraphicsSetSmoothingMode($hImageLabel, 4)
    $aCtrlSize[0] -= 20
    $aCtrlSize[2] += 40
    $aCtrlSize[3] += 20
    Case BitAND($iStyle, $RBS_TICKS_BELOW_LEFT)
    $hPenTicks = _GDIPlus_PenCreate($sTickColor)
    $hBitmapTicks = _GDIPlus_BitmapCreateFromGraphics($width, 6, $hGraphic)
    $hBitmapLabel = _GDIPlus_BitmapCreateFromGraphics($width +40, 12, $hGraphic)
    $hImageTicks = _GDIPlus_ImageGetGraphicsContext($hBitmapTicks)
    _GDIPlus_GraphicsSetSmoothingMode($hImageTicks, 4)
    $aCtrlSize[3] += 8
    EndSelect
    DllStructSetData($tRangeCtrl, "Style" , $iStyle)
    DllStructSetData($tRangeCtrl, "Graphics" , $hGraphic)
    DllStructSetData($tRangeCtrl, "BrushRange", $hBrushRange)
    DllStructSetData($tRangeCtrl, "BrushBack" , $hBrushBack)
    DllStructSetData($tRangeCtrl, "PenMarker" , $hPenMarker)
    DllStructSetData($tRangeCtrl, "PenTicks" , $hPenTicks)
    DllStructSetData($tRangeCtrl, "Format" , $hFormat)
    DllStructSetData($tRangeCtrl, "Family" , $hFamily)
    DllStructSetData($tRangeCtrl, "Font" , $hFont)
    DllStructSetData($tRangeCtrl, "BrushFont" , $hBrushFont)
    DllStructSetData($tRangeCtrl, "Bitmap" , $hBitmapBar, 1)
    DllStructSetData($tRangeCtrl, "Bitmap" , $hBitmapTicks, 2)
    DllStructSetData($tRangeCtrl, "Bitmap" , $hBitmapLabel, 3)
    DllStructSetData($tRangeCtrl, "Image" , $hImageBar, 1)
    DllStructSetData($tRangeCtrl, "Image" , $hImageTicks, 2)
    DllStructSetData($tRangeCtrl, "Image" , $hImageLabel, 3)
    DllStructSetData($tRangeCtrl, "RECTBar" , $x, 1)
    DllStructSetData($tRangeCtrl, "RECTBar" , $y, 2)
    DllStructSetData($tRangeCtrl, "RECTBar" , $width, 3)
    DllStructSetData($tRangeCtrl, "RECTBar" , $height, 4)
    DllStructSetData($tRangeCtrl, "RECTCtrl" , $aCtrlSize[0], 1)
    DllStructSetData($tRangeCtrl, "RECTCtrl" , $aCtrlSize[1], 2)
    DllStructSetData($tRangeCtrl, "RECTCtrl" , $aCtrlSize[0] +$aCtrlSize[2], 3)
    DllStructSetData($tRangeCtrl, "RECTCtrl" , $aCtrlSize[1] +$aCtrlSize[3], 4)
    DllStructSetData($tRangeCtrl, "Marker" , 0, 1)
    DllStructSetData($tRangeCtrl, "Marker" , $width, 2)
    DllStructSetData($tRangeCtrl, "Ticks" , 2)
    DllStructSetData($tRangeCtrl, "Label" , '0 100')
    DllStructSetData($tRangeCtrl, "RECTleft" , $x - 4, 1)
    DllStructSetData($tRangeCtrl, "RECTleft" , $y - 2, 2)
    DllStructSetData($tRangeCtrl, "RECTleft" , $x + 4, 3)
    DllStructSetData($tRangeCtrl, "RECTleft" , $y + $height + 2, 4)
    DllStructSetData($tRangeCtrl, "RECTright" , $x + $width - 4, 1)
    DllStructSetData($tRangeCtrl, "RECTright" , $y - 2, 2)
    DllStructSetData($tRangeCtrl, "RECTright" , $x + $width + 4, 3)
    DllStructSetData($tRangeCtrl, "RECTright" , $y + $height + 2, 4)
    Return $tRangeCtrl
    EndFunc ;==>_GDIPlus_RangeBar_Create

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

    ; =================================================================================================
    ; Anzahl Ticks setzen, min. 2 (Anfang u. Ende), Zehner-Teilung = 11 etc.
    ; $sLabel = erster und letzter Wert, Leerzeichen als Trenner
    ; Berechnung Labelwerte für einzelne Ticks automatisch
    ; =================================================================================================
    Func _GDIPlus_RangeBar_SetTickLimit(ByRef $tRangeCtrl, $iTickCount = 2, $sLabel = '') ; Anzahl Ticks setzen, min. 2 (Anfang u. Ende), Zehner-Teilung = 11 etc.
    Local $iMode = 6
    If StringLen($sLabel) Then DllStructSetData($tRangeCtrl, "Label", StringReplace($sLabel, ',', '.')) ; $sLabel = erster und letzter Wert, Leerzeichen als Trenner
    If $iTickCount < 2 Then $iTickCount = 2
    DllStructSetData($tRangeCtrl, "Ticks", $iTickCount)
    __GDIPlus_RangeBar_Draw($tRangeCtrl, $iMode)
    EndFunc ;==>_GDIPlus_RangeBar_SetTickLimit

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

    ; =================================================================================================
    ; Limit setzen (Anfangswert / Endwert) als Leerzeichen getrennter String
    ; =================================================================================================
    Func _GDIPlus_RangeBar_SetLimit(ByRef $tRangeCtrl, $sLimit = '0 100')
    Local $tmp = StringSplit($sLimit, ' '), $iMode = 4
    If $tmp[0] <> 2 Then Return SetError(1, 0, 0)
    DllStructSetData($tRangeCtrl, "Label", $sLimit)
    __GDIPlus_RangeBar_Draw($tRangeCtrl, $iMode)
    Return 1
    EndFunc ;==>_GDIPlus_RangeBar_SetLimit

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

    ; =================================================================================================
    ; Range setzen, Anfang/Ende als Prozentwert
    ; =================================================================================================
    Func _GDIPlus_RangeBar_SetRange(ByRef $tRangeCtrl, $iStartRange = 0, $iEndRange = 100) ; Range Anfang/Ende als Prozentwert
    If $iEndRange < $iStartRange Then
    Local $tmp = $iEndRange
    $iEndRange = $iStartRange
    $iStartRange = $tmp
    EndIf
    Local $iMode = 4
    Local $x = DllStructGetData($tRangeCtrl, "RECTBar", 1)
    Local $width = DllStructGetData($tRangeCtrl, "RECTBar", 3)
    Local $xLeft = Int($iStartRange * $width / 100)
    Local $xRight = Int($iEndRange * $width / 100)
    DllStructSetData($tRangeCtrl, "Marker", $xLeft, 1)
    DllStructSetData($tRangeCtrl, "Marker", $xRight, 2)
    DllStructSetData($tRangeCtrl, "RECTleft", $x + $xLeft - 8, 1)
    DllStructSetData($tRangeCtrl, "RECTleft", $x + $xLeft + 8, 3)
    DllStructSetData($tRangeCtrl, "RECTright", $x + $xRight - 8, 1)
    DllStructSetData($tRangeCtrl, "RECTright", $x + $xRight + 8, 3)
    __GDIPlus_RangeBar_Draw($tRangeCtrl, $iMode)
    EndFunc ;==>_GDIPlus_RangeBar_SetRange

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

    ; =================================================================================================
    ; Range-Ctrl neu zeichnen
    ; $iDrawMode: 1- nur Bar, 2- nur Ticks, 4- nur Label (Kombinationen), enthaltenes Element wird gezeichnet
    ; =================================================================================================
    Func __GDIPlus_RangeBar_Draw(ByRef $tRangeCtrl, $iDrawMode = 1, $iWndColor = 0xD4D0C8) ; Range-Ctrl zeichnen
    Local $hGraphic = DllStructGetData($tRangeCtrl, "Graphics")
    Local $hBrushRange = DllStructGetData($tRangeCtrl, "BrushRange")
    Local $hBrushBack = DllStructGetData($tRangeCtrl, "BrushBack")
    Local $hPenMarker = DllStructGetData($tRangeCtrl, "PenMarker")
    Local $hPenTicks = DllStructGetData($tRangeCtrl, "PenTicks")
    Local $hBitmapBar = DllStructGetData($tRangeCtrl, "Bitmap", 1)
    Local $hBitmapTicks = DllStructGetData($tRangeCtrl, "Bitmap", 2)
    Local $hBitmapLabel = DllStructGetData($tRangeCtrl, "Bitmap", 3)
    Local $hImageBar = DllStructGetData($tRangeCtrl, "Image", 1)
    Local $hImageTicks = DllStructGetData($tRangeCtrl, "Image", 2)
    Local $hImageLabel = DllStructGetData($tRangeCtrl, "Image", 3)
    Local $iStyle = DllStructGetData($tRangeCtrl, "Style")
    Local $x = DllStructGetData($tRangeCtrl, "RECTBar", 1)
    Local $y = DllStructGetData($tRangeCtrl, "RECTBar", 2)
    Local $width = DllStructGetData($tRangeCtrl, "RECTBar", 3)
    Local $height = DllStructGetData($tRangeCtrl, "RECTBar", 4)
    Local $lM = DllStructGetData($tRangeCtrl, "Marker", 1)
    Local $rM = DllStructGetData($tRangeCtrl, "Marker", 2)
    Local $ticks = DllStructGetData($tRangeCtrl, "Ticks")
    Local $drawBar = False, $drawTicks = False, $drawLabel = False
    If BitAND($iDrawMode, 1) Then $drawBar = True
    If BitAND($iDrawMode, 2) Then $drawTicks = True
    If BitAND($iDrawMode, 4) Then $drawLabel = True
    Local $hFormat, $hFamily, $hFont, $hBrushFont, $tLayout, $aInfo, $chrX
    Local $rangeWidth = $rM - $lM, $aLabel, $LabelStep, $text
    Local $left = $x, $step, $bTicks = False, $bLabel = False, $bB60 = False
    If BitAND($iStyle, BitOR($RBS_TICKS_BELOW_LEFT,$RBS_TICKS_ONTOP_RIGHT)) Then $bTicks = True
    If BitAND($iStyle, $RBS_LABEL) Then $bLabel = True
    If $bLabel Then
    If BitAND($iStyle, $RBS_BASE60) Then $bB60 = True
    $aLabel = StringSplit(DllStructGetData($tRangeCtrl, "Label"), ' ', 2)
    $LabelStep = ($aLabel[1] - $aLabel[0]) / ($ticks - 1)
    EndIf
    If $drawBar Then
    _GDIPlus_GraphicsClear($hImageBar, '0xFF' & Hex($iWndColor, 6))
    _GDIPlus_GraphicsFillRect($hImageBar, 0, 0, $width, $height, $hBrushBack)
    _GDIPlus_GraphicsFillRect($hImageBar, $lM, 0, $rangeWidth, $height, $hBrushRange)
    _GDIPlus_GraphicsDrawLine($hImageBar, $lM, 0, $lM, $height - 1, $hPenMarker)
    _GDIPlus_GraphicsDrawLine($hImageBar, $rM-1, 0, $rM-1, $height - 1, $hPenMarker)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmapBar, $x, $y, $width, $height)
    EndIf
    If $drawLabel And $bLabel Then
    _GDIPlus_GraphicsClear($hImageLabel, '0xFF' & Hex($iWndColor, 6))
    $hFormat = DllStructGetData($tRangeCtrl, "Format")
    $hFamily = DllStructGetData($tRangeCtrl, "Family")
    $hFont = DllStructGetData($tRangeCtrl, "Font")
    $hBrushFont = DllStructGetData($tRangeCtrl, "BrushFont")
    EndIf
    If $drawTicks And $bTicks Then
    _GDIPlus_GraphicsClear($hImageTicks, '0xFF' & Hex($iWndColor, 6))
    If $ticks > 2 Then
    $step = Int($width / ($ticks - 1))
    $left = 0
    For $i = 0 To $ticks - 2
    _GDIPlus_GraphicsDrawLine($hImageTicks, $left, 0, $left, 6, $hPenTicks)
    If $bLabel Then
    Switch $i
    Case 0
    $text = $aLabel[0]
    Case Else
    $text = Round($i * $LabelStep + $aLabel[0], 2)
    EndSwitch
    If $bB60 Then $text = __DecToBase60($text)
    $aInfo = __TextSize($tRangeCtrl, $text)
    $chrX = $x + $left - (Ceiling(DllStructGetData($aInfo[0], "Width") / 2))
    $tLayout = _GDIPlus_RectFCreate($chrX)
    _GDIPlus_GraphicsDrawStringEx($hImageLabel, $text, $hFont, $tLayout, $hFormat, $hBrushFont)
    EndIf
    $left += $step
    Next
    _GDIPlus_GraphicsDrawLine($hImageTicks, $width-1, 0, $width-1, 6, $hPenTicks)
    If $bLabel Then
    $text = $aLabel[1]
    If $bB60 Then $text = __DecToBase60($text)
    $aInfo = __TextSize($tRangeCtrl, $text)
    $chrX = $x + $width -1 - (Ceiling(DllStructGetData($aInfo[0], "Width") / 2))
    $tLayout = _GDIPlus_RectFCreate($chrX)
    _GDIPlus_GraphicsDrawStringEx($hImageLabel, $text, $hFont, $tLayout, $hFormat, $hBrushFont)
    EndIf
    Else
    _GDIPlus_GraphicsDrawLine($hImageTicks, 0, 0, 0, 6, $hPenTicks)
    _GDIPlus_GraphicsDrawLine($hImageTicks, $width-1, 0, $width-1, 6, $hPenTicks)
    If $bLabel Then
    $text = $aLabel[0]
    If $bB60 Then $text = __DecToBase60($aLabel[0])
    $aInfo = __TextSize($tRangeCtrl, $text)
    $chrX = $x - (Ceiling(DllStructGetData($aInfo[0], "Width") / 2))
    $tLayout = _GDIPlus_RectFCreate($chrX)
    _GDIPlus_GraphicsDrawStringEx($hImageLabel, $text, $hFont, $tLayout, $hFormat, $hBrushFont)
    $text = $aLabel[1]
    If $bB60 Then $text = __DecToBase60($aLabel[1])
    $aInfo = __TextSize($tRangeCtrl, $text)
    $chrX = $x + $width -1 - (Ceiling(DllStructGetData($aInfo[0], "Width") / 2))
    $tLayout = _GDIPlus_RectFCreate($chrX, 0, 0, DllStructGetData($aInfo[0], "Height"))
    _GDIPlus_GraphicsDrawStringEx($hImageLabel, $text, $hFont, $tLayout, $hFormat, $hBrushFont)
    EndIf
    EndIf
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmapTicks, $x, $y+$height+2, $width, 6)
    If $bLabel Then _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmapLabel, $x-20, $y+$height+8, $width+40, 12)
    EndIf
    EndFunc ;==>__GDIPlus_RangeBar_Draw

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

    ; =================================================================================================
    ; Rückgabe Array aktueller Start- u. Endwert der Range [links_%,rechts_%,links_Wert,rechts_Wert]
    ; =================================================================================================
    Func _GDIPlus_RangeBar_GetRange($tRangeCtrl) ; Rückgabe aktueller Start- u. Endwert der Range [links_%,rechts_%,links_Wert,rechts_Wert]
    Local $width = DllStructGetData($tRangeCtrl, "RECTBar", 3)
    Local $lMpercent = Round(DllStructGetData($tRangeCtrl, "Marker", 1) * 100 / $width, 2)
    Local $rMpercent = Round(DllStructGetData($tRangeCtrl, "Marker", 2) * 100 / $width, 2)
    Local $aLimit = StringSplit(DllStructGetData($tRangeCtrl, "Label"), ' ', 2)
    Local $FullValue = $aLimit[1] - $aLimit[0]
    Local $aOut[4] = [$lMpercent, _
    $rMpercent, _
    $aLimit[0] + Round($lMpercent * $FullValue / 100, 2), _
    $aLimit[0] + Round($rMpercent * $FullValue / 100, 2)]
    Return $aOut
    EndFunc ;==>_GDIPlus_RangeBar_GetRange

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

    ; =================================================================================================
    ; Controlgröße ermitteln
    ; tatsächliche Größe je nach Style wird als Einzelwert und als RECT-Struktur zurückgegeben
    ; =================================================================================================
    Func _GDIPlus_RangeBar_GetSize($tRangeCtrl) ; [$x,$y,$width,$height,$tRECT]
    Local $aOut[5] = [ _
    DllStructGetData($tRangeCtrl, "RECTCtrl", 1), _
    DllStructGetData($tRangeCtrl, "RECTCtrl", 2), _
    DllStructGetData($tRangeCtrl, "RECTCtrl", 3) - DllStructGetData($tRangeCtrl, "RECTCtrl", 1), _
    DllStructGetData($tRangeCtrl, "RECTCtrl", 4) - DllStructGetData($tRangeCtrl, "RECTCtrl", 2)]
    $aOut[4] = DllStructCreate("int Left;int Top;int Right;int Bottom")
    DllCall($Dll_user32, 'long', 'SetRect', 'ptr', DllStructGetPtr($aOut[4]), _
    'long', $aOut[0], 'long', $aOut[1], 'long', $aOut[0]+$aOut[2], 'long', $aOut[1]+$aOut[3])
    Return $aOut
    EndFunc

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

    ; =================================================================================================
    ; Ressourcen löschen
    ; =================================================================================================
    Func _GDIPlus_RangeBar_Dispose($tRangeCtrl, $bGDI_down = True) ; Ressourcen löschen
    _GDIPlus_GraphicsDispose(DllStructGetData($tRangeCtrl, "Graphics"))
    _GDIPlus_BrushDispose(DllStructGetData($tRangeCtrl, "BrushRange"))
    _GDIPlus_BrushDispose(DllStructGetData($tRangeCtrl, "BrushBack"))
    _GDIPlus_BrushDispose(DllStructGetData($tRangeCtrl, "BrushFont"))
    _GDIPlus_PenDispose(DllStructGetData($tRangeCtrl, "PenMarker"))
    _GDIPlus_PenDispose(DllStructGetData($tRangeCtrl, "PenTicks"))
    _GDIPlus_StringFormatDispose(DllStructGetData($tRangeCtrl, "Format"))
    _GDIPlus_FontFamilyDispose(DllStructGetData($tRangeCtrl, "Family"))
    _GDIPlus_FontDispose(DllStructGetData($tRangeCtrl, "Font"))
    _GDIPlus_BitmapDispose(DllStructGetData($tRangeCtrl, "Bitmap"))
    If $bGDI_down Then _GDIPlus_Shutdown()
    DllClose($Dll_user32)
    EndFunc ;==>_GDIPlus_RangeBar_Dispose

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

    #region - Hilfsfunktionen
    Func __WinStateCheck() ; prüft ob GDI+ Ctrl neu gezeichnet werden muß
    Local $iWinState = WinGetState($guiRange)
    Local $iMode = 1+2+4
    If BitAND($iWinState, 8) And Not $bIsActive Then
    $bIsActive = True
    Return __GDIPlus_RangeBar_Draw($RangeCtrl, $iMode)
    ElseIf Not BitAND($iWinState, 8) And $bIsActive Then
    $bIsActive = False
    EndIf
    Local $pos = WinGetPos($guiRange)
    Local $moved = 0, $aCheckNew[4] = [$pos[0], $pos[1], $pos[0], $pos[1]]
    For $i = 0 To 3
    If $aCheck[$i] <> $aCheckNew[$i] Then
    $aCheck[$i] = $aCheckNew[$i]
    $moved = 1
    EndIf
    Next
    If $moved Then __GDIPlus_RangeBar_Draw($RangeCtrl, $iMode)
    EndFunc ;==>__WinStateCheck

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

    Func __MoveMarker(ByRef $tRangeCtrl, $iMarker, $iX) ; $iMarker: 0=links, 1=rechts
    Local $x = DllStructGetData($tRangeCtrl, "RECTBar", 1)
    Local $w = DllStructGetData($tRangeCtrl, "RECTBar", 3)
    Local $aElement[2] = ["RECTleft", "RECTright"], $aIndex[2] = [1, 2]
    Local $oldMarker = DllStructGetData($tRangeCtrl, "Marker", $aIndex[$iMarker])
    Local $lM = DllStructGetData($tRangeCtrl, "Marker", 1)
    Local $rM = DllStructGetData($tRangeCtrl, "Marker", 2)
    Local $iMode = 1, $next = 1
    If Abs($oldMarker-$iX) > 2 Then $next = 2
    If $iX - $x < $oldMarker Then
    $iX = $oldMarker - $next
    ElseIf $iX - $x > $oldMarker Then
    $iX = $oldMarker + $next
    Else
    Return
    EndIf
    Switch $iMarker
    Case 0
    If $iX < 0 Then $iX = 0
    If $iX >= $rM Then $iX = $rM - 1
    Case 1
    If $iX <= $lM Then $iX = $lM + 1
    If $iX > $w Then $iX = $w
    EndSwitch
    DllStructSetData($tRangeCtrl, "Marker", $iX, $aIndex[$iMarker])
    DllStructSetData($tRangeCtrl, $aElement[$iMarker], $x + $iX - 4, 1)
    DllStructSetData($tRangeCtrl, $aElement[$iMarker], $x + $iX + 4, 3)
    __GDIPlus_RangeBar_Draw($tRangeCtrl, $iMode)

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

    ; === Werte in GUI anzeigen (nur Test) ====
    _showValue()
    ; ==========================================
    EndFunc ;==>__MoveMarker

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

    Func __TextSize(ByRef $tRangeCtrl, $nText)
    If $nText = '' Then Return
    Local $hGraphic = DllStructGetData($tRangeCtrl, "Graphics")
    Local $hFormat = DllStructGetData($tRangeCtrl, "Format")
    Local $hFamily = DllStructGetData($tRangeCtrl, "Family")
    Local $hFont = DllStructGetData($tRangeCtrl, "Font")
    Local $tLayout = _GDIPlus_RectFCreate()
    Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $nText, $hFont, $tLayout, $hFormat)
    Return $aInfo
    EndFunc ;==>__TextSize

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

    Func __DecToBase60($i)
    Return Floor($i) & ':' & StringFormat('%02d', Round(($i - Floor($i))*60))
    EndFunc ;==>__DecToBase60
    #endregion

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

    Func _WM_MOUSEMOVE($hWnd, $uMsg, $wParam, $lParam)
    Local $x, $y, $x1, $y1, $xC, $xM, $retL, $retR, $posWin, $xPos = BitAND($lParam, 0xFFFF), $yPos = BitShift($lParam, 16)
    Local Const $MK_LBUTTON = 1, $MK_CONTROL = 8
    $xM = DllStructGetData($RangeCtrl, "Mouse")
    If Not IsDllStruct($tLeftMarker) Or Not IsDllStruct($tRightMarker) Or Not IsDllStruct($tRange) Then
    $tLeftMarker = DllStructCreate("int Left;int Top;int Right;int Bottom")
    $tRightMarker = DllStructCreate("int Left;int Top;int Right;int Bottom")
    $tRange = DllStructCreate("int Left;int Top;int Right;int Bottom")
    EndIf
    $x = DllStructGetData($RangeCtrl, "RECTleft", 1)
    $y = DllStructGetData($RangeCtrl, "RECTleft", 2)
    $x1 = DllStructGetData($RangeCtrl, "RECTleft", 3)
    $y1 = DllStructGetData($RangeCtrl, "RECTleft", 4)
    DllCall($Dll_user32, 'long', 'SetRect', 'ptr', DllStructGetPtr($tLeftMarker), 'long', $x, 'long', $y, 'long', $x1, 'long', $y1)
    $x = DllStructGetData($RangeCtrl, "RECTright", 1)
    $y = DllStructGetData($RangeCtrl, "RECTright", 2)
    $x1 = DllStructGetData($RangeCtrl, "RECTright", 3)
    $y1 = DllStructGetData($RangeCtrl, "RECTright", 4)
    DllCall($Dll_user32, 'long', 'SetRect', 'ptr', DllStructGetPtr($tRightMarker), 'long', $x, 'long', $y, 'long', $x1, 'long', $y1)
    $xC = DllStructGetData($RangeCtrl, "RECTBar", 1)
    $x = DllStructGetData($RangeCtrl, "Marker", 1) + $xC
    $y = DllStructGetData($RangeCtrl, "RECTBar", 2)
    $x1 = DllStructGetData($RangeCtrl, "Marker", 2) + $xC
    $y1 = DllStructGetData($RangeCtrl, "RECTBar", 4) + $y
    DllCall($Dll_user32, 'long', 'SetRect', 'ptr', DllStructGetPtr($tRange), 'long', $x, 'long', $y, 'long', $x1, 'long', $y1)
    $retLM = DllCall($Dll_user32, 'long', 'PtInRect', 'ptr', DllStructGetPtr($tLeftMarker), 'long', $xPos, 'long', $yPos)
    $retRM = DllCall($Dll_user32, 'long', 'PtInRect', 'ptr', DllStructGetPtr($tRightMarker), 'long', $xPos, 'long', $yPos)
    Local $posWin = WinGetPos($hWnd)
    Switch $wParam
    Case $MK_LBUTTON ; Maus bewegt und Links geklickt
    If $retLM[0] > 0 Then
    __MoveMarker($RangeCtrl, 0, $xPos)
    ElseIf $retRM[0] > 0 Then
    __MoveMarker($RangeCtrl, 1, $xPos)
    EndIf
    ;~ Case $MK_CONTROL ; Maus bewegt und STRG gedrückt
    ;~ $retR = DllCall($Dll_user32, 'long', 'PtInRect', 'ptr', DllStructGetPtr($tRange), 'long', $xPos, 'long', $yPos)
    ;~ If $retR[0] > 0 Then
    ;~ If ($xM > $xPos + 10) Or ($xM < $xPos - 10) Then DllStructSetData($RangeCtrl, "Mouse", $xPos)
    ;~ __MoveRange($RangeCtrl, $xPos) ;ConsoleWrite(@SEC & ' STRG-Mouse' & @CRLF)
    ;~ EndIf
    Case Else
    If $retLM[0] > 0 Or $retRM[0] > 0 Then
    If Not $bSetCursor Then
    GUISetCursor(0)
    $bSetCursor = True
    EndIf
    Else
    If $bSetCursor Then
    GUISetCursor(-1)
    $bSetCursor = False
    EndIf
    EndIf
    EndSwitch
    Return 0
    EndFunc ;==>_WM_MOUSEMOVE

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

    Func _showValue() ; Testanzeige
    Local $aRange = _GDIPlus_RangeBar_GetRange($RangeCtrl)
    GUICtrlSetData($inLeftpercent, $aRange[0])
    GUICtrlSetData($inRightpercent, $aRange[1])
    GUICtrlSetData($inLeftvalue, __DecToBase60($aRange[2]))
    GUICtrlSetData($inRightvalue, __DecToBase60($aRange[3]))
    GUICtrlSetData($inValue, __DecToBase60($aRange[3] - $aRange[2]))
    EndFunc

    [/autoit]
    • Offizieller Beitrag

    Schönes und nützliches Control-Element, aber das mit dem abrutschen musst Du noch hinkriegen. Sooo langsam und präzise kriege ich das nur mit meiner Logitech-Lasermaus hin. ^^

    Unter Win7 (64 Bit) musst Du

    [autoit]

    #AutoIt3Wrapper_UseX64=n

    [/autoit]


    an den Anfang des Skripts setzen, sonst erscheint der Hand-Mauszeiger nicht und man kann nichts verstellen.

    • Offizieller Beitrag

    aber das mit dem abrutschen musst Du noch hinkriegen. Sooo langsam und präzise kriege ich das nur mit meiner Logitech-Lasermaus hin.


    Ja, da grübele ich schon etliche Stunden drüber. Ein paar Lösungsansätze muß ich noch probieren - aber teilweise würde das eine kpl. Änderung des Konzeptes mit sich bringen, darum will ich erst mal alles, was in der Variante machbar ist ausloten.
    Falls irgendwer da einen zündenden Gedanken hat - immer her damit.
    Das Catchen der Marker mittels zusätzlicher Taste (Maus über Marker + Taste und Maus bleibt an Marker gekoppelt bis wieder Taste gedrückt) wollte ich eigentlich vermeiden und würde es nur als allerletztes Mittel verwenden wollen.

  • Ich kann Oscar nichts hinzufügen ^^
    Wenn das gefixt wird ist es echte Spitzenklasse :thumbup:

    mfg Ubuntu

    • Offizieller Beitrag

    Ich kann mir zwar gerade nicht vorstellen, dass ich das jemals brauchen werde


    :D Das Einsatzgebiet ist sicher nicht übermäßig groß, aber mich interessierte vor allem einmal selbst ein dynamisches Control zu erstellen. Insofern war es eine Herausforderung.

  • Hallo BugFix,

    sieht gut aus :thumbup: Das mit dem Abrutschen passiert bei meinem NetBook auf dem Touchpad komischerweise nicht. Du könntest aber mit _MouseTrap versuchen die Maus während des Ziehens innerhalb kleiner Grenzen zu halten, (habe das Skript aber noch nicht analysiert)

    mfg (Auto)Bert

  • klasse Sache auf die Idee hab ich dich wohl gebracht, so ein teil hab ich nämlich gesucht und hättest du mir gesagt, dass du ne UDF machst hätt ich nicht selber rumwurschteln müssen ^^

    Das finden von Rechtschreibfehlern muss sofort und unverzüglich dem Autor gemeldet werden. Das eigennützige Verwenden dieser Rechtschreibfehler ist strengstens untersagt und kann mit Freiheitsenzug bestraft werden.