KnobControl (ehem. ControllerGadget)
Verfasst: 18.03.2012 18:12
Die Möglichkeiten des CanvasGadget sind ja praktisch unendlich... (Kann-was-Gadget
)
Hier habe ich mal einen Gadget Typen entwickelt den ich "ControllerGadget"
nenne.
Er verhält sich wie ein Drehregler, - also mit linker Maustaste draufklicken,
gedrückt halten und den Regler nach links oder rechts drehen.
Minimal- und Maximalwert sowie Minimal- und Maximalwinkel lassen sich einstellen.
Wird der Flagwert #ControllerGadget_Infinite übergeben, dann besitzt das Gadget
keinen "Anschlag", d.h. es lässt sich unendlich nach links oder rechts drehen.
- Name geändert: "KnobControl" gefällt mir besser als ControllerGadget (Danke RSBasic, für den Hinweis)
- Flag "#KnobControl_LinearPointer" hinzugefügt. (zeichnet einen linearen Zeiger)
- Flag "#KnobControl_Smooth" hinzugefügt. (stufenloses Drehen)
- Farbwert "ColorBorder" hinzugefügt. (Randfarbe des Drehreglers)
- Procedure "KnobControl_SetColor" hinzugefügt. (eigene Farben definieren)
- Darstellung der Drehregler geändert.
[/size]

Hier habe ich mal einen Gadget Typen entwickelt den ich "ControllerGadget"
nenne.
Er verhält sich wie ein Drehregler, - also mit linker Maustaste draufklicken,
gedrückt halten und den Regler nach links oder rechts drehen.
Minimal- und Maximalwert sowie Minimal- und Maximalwinkel lassen sich einstellen.
Wird der Flagwert #ControllerGadget_Infinite übergeben, dann besitzt das Gadget
keinen "Anschlag", d.h. es lässt sich unendlich nach links oder rechts drehen.
- Name geändert: "KnobControl" gefällt mir besser als ControllerGadget (Danke RSBasic, für den Hinweis)
- Flag "#KnobControl_LinearPointer" hinzugefügt. (zeichnet einen linearen Zeiger)
- Flag "#KnobControl_Smooth" hinzugefügt. (stufenloses Drehen)
- Farbwert "ColorBorder" hinzugefügt. (Randfarbe des Drehreglers)
- Procedure "KnobControl_SetColor" hinzugefügt. (eigene Farben definieren)
- Darstellung der Drehregler geändert.
Code: Alles auswählen
; Knob-Control
; ----------------
; March 2012 Mr.L
;
; left-click on a controller and hold the button down
; turn the 'KnobControl' left or right
EnableExplicit
Structure KnobControlData
Canvas.i
Radius.w
MinAngle.i
MaxAngle.i
MinValue.i
MaxValue.i
State.i
Value.i
Angle.i
LastAngle.i
Steps.i
Flags.i
HasFocus.b
ColorBackGround.i
ColorForeGround.i
ColorBorder.i
ColorShadow.i
ColorHighLight.i
EndStructure
Enumeration
#KnobControl_Background
#KnobControl_Foreground
#KnobControl_Border
#KnobControl_Highlight
#KnobControl_Shadow
EndEnumeration
#KnobControl_Ticks = 1 ; draw ticks around the control
#KnobControl_LinearPointer = 2 ; draw a linear pointer instead of a circle
#KnobControl_Infinite = 4 ; infinite turning to left or right
#KnobControl_Smooth = 8 ; enable smooth movement
Declare KnobControl(Gadget , x,y,Radius , MinValue=0 , MaxValue=100 , Steps=360 , MinAngle=0 , MaxAngle=360 , Flags=0)
Declare KnobControl_GetValue(Gadget)
Declare KnobControl_SetValue(Gadget , Value)
Declare KnobControl_SetColor(Gadget , ColorType , Color)
Declare KnobControl_Event(Gadget , Event)
Declare KnobControl_Free(Gadget)
Procedure __KnobControl_Redraw__(*KnobControl.KnobControlData)
; all the drawing stuff
Protected a,s,x,y,minAngle,maxAngle
If *KnobControl
StartDrawing(CanvasOutput(*KnobControl\Canvas))
With *KnobControl
Box(0,0,OutputWidth(),OutputHeight() , \ColorBackGround)
; draw the 'clock-face'
Circle(\Radius , \Radius , \Radius - 1 , \ColorBorder)
DrawingMode(#PB_2DDrawing_Gradient)
If \HasFocus
GradientColor(0.0 , \ColorHighLight)
Else
GradientColor(0.0 , \ColorForeGround)
EndIf
GradientColor(1.0 , \ColorShadow)
CircularGradient(\Radius * 0.65 , \Radius * 0.65 , \Radius * 3)
Circle(\Radius , \Radius , \Radius - 3)
DrawingMode(#PB_2DDrawing_Default)
If \Flags & #KnobControl_Ticks
; draw the 'ticks'
If \MinAngle Or \MaxAngle
minAngle = \MinAngle + 90
maxAngle = \MaxAngle + 90
Else
minAngle = 0
maxAngle = 360
EndIf
If (maxAngle - minAngle) And \Steps
a = minAngle
s = (maxAngle - minAngle) / \Steps
Repeat
x = \Radius - Cos(Radian(a)) * (\Radius * 0.85)
y = \Radius - Sin(Radian(a)) * (\Radius * 0.85)
Circle(x,y,1,\ColorShadow)
a + s
Until a > maxAngle Or a > (minAngle + 360)
EndIf
EndIf
; draw the 'clockhand'
x = \Radius - Cos(Radian(\State + 90)) * (\Radius * 0.65)
y = \Radius - Sin(Radian(\State + 90)) * (\Radius * 0.65)
If \Flags & #KnobControl_LinearPointer
LineXY(\Radius , \Radius , x , y , \ColorShadow)
LineXY(\Radius+1 , \Radius , x + 1 , y , \ColorShadow)
LineXY(\Radius , \Radius+1 , x , y + 1 , \ColorShadow)
LineXY(\Radius+1 , \Radius+1 , x + 1 , y + 1 , \ColorShadow)
Circle(\Radius , \Radius , 3 , \ColorShadow)
Circle(\Radius , \Radius , 1 , \ColorBackGround)
Else
Circle(x,y,3,\ColorShadow)
Circle(x,y,1,\ColorForeGround)
EndIf
EndWith
StopDrawing()
EndIf
EndProcedure
Procedure __KnobControl_Update__(*KnobControl.KnobControlData , lockAngle = #False)
; Update angle and value
Protected angle.d , stepSize
If *KnobControl
With *KnobControl
If \Flags & #KnobControl_Infinite = 0
; clamp angle
If \Angle < \MinAngle
\Angle = \MinAngle
ElseIf \Angle > \MaxAngle
\Angle = \MaxAngle
EndIf
EndIf
If \Steps
angle = (\MaxAngle - \MinAngle)
stepSize = angle / \Steps
If angle And stepSize
; convert angle to value
If lockAngle Or (\Flags & #KnobControl_Smooth) = #False
\State = Round(\Angle / (stepSize * 1.0) , #PB_Round_Nearest) * stepSize
Else
\State = \Angle
EndIf
\Value = (\State - \MinAngle) * ((\MaxValue - \MinValue) / angle) + \MinValue
Else
If lockAngle Or (\Flags & #KnobControl_Smooth) = #False
\State = Round(\Angle / (\Steps * 1.0) , #PB_Round_Nearest) * \Steps
Else
\State = \Angle
EndIf
\Value = \State
EndIf
EndIf
If \MinValue Or \MaxValue
; keep value inside range
If \Value > \MaxValue
\Value = Mod(\Value , \MaxValue)
EndIf
If \Value < \MinValue
\Value = Mod(\Value , \MaxValue) + \MaxValue
EndIf
EndIf
EndWith
__KnobControl_Redraw__(*KnobControl)
EndIf
EndProcedure
Procedure __KnobControl_Get__(Gadget)
; Return the KnobControlData of the 'Gadget'
If IsGadget(Gadget) = 0 Or GadgetType(Gadget) <> #PB_GadgetType_Canvas
ProcedureReturn #Null
EndIf
ProcedureReturn GetGadgetData(Gadget)
EndProcedure
Procedure KnobControl(Gadget , x,y,Radius , MinValue=0 , MaxValue=100 , Steps=360 , MinAngle=0 , MaxAngle=360 , Flags=0)
; Create a new KnobControl and return its handle
Protected *KnobControl.KnobControlData
*KnobControl = __KnobControl_Get__(Gadget)
If *KnobControl
; if a control with this ID already exists - delete it
KnobControl_Free(Gadget)
EndIf
If MaxAngle < MinAngle
Swap MinAngle , MaxAngle
EndIf
If MaxValue < MinValue
Swap MinValue , MaxValue
EndIf
If Gadget = #PB_Any
Gadget = CanvasGadget(#PB_Any , x,y,Radius * 2,Radius * 2 , #PB_Canvas_Keyboard)
Else
CanvasGadget(Gadget , x,y,Radius * 2,Radius * 2 , #PB_Canvas_Keyboard)
EndIf
If IsGadget(Gadget)
*KnobControl = AllocateMemory(SizeOf(KnobControlData))
If *KnobControl
With *KnobControl
\Canvas = Gadget
\MinAngle = MinAngle
\MaxAngle = MaxAngle
\MinValue = MinValue
\MaxValue = MaxValue
\Angle = MinAngle
; \State = MinValue
\Radius = Radius
\Flags = Flags
\Steps = Steps
If \Steps < 1
\Steps = 1
EndIf
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
\ColorBackGround = GetSysColor_(#COLOR_3DFACE)
\ColorForeGround = GetSysColor_(#COLOR_3DLIGHT)
\ColorHighLight = GetSysColor_(#COLOR_3DHIGHLIGHT)
\ColorBorder = GetSysColor_(#COLOR_3DSHADOW)
\ColorShadow = GetSysColor_(#COLOR_3DDKSHADOW)
CompilerElse
\ColorBackGround = $F2F1F0
\ColorForeGround = $C8D0D4
\ColorHighLight = $FFFFFF
\ColorBorder = $808080
\ColorShadow = $404040
CompilerEndIf
EndWith
SetGadgetData(Gadget , *KnobControl)
__KnobControl_Update__(*KnobControl)
Else
FreeGadget(Gadget)
Gadget = 0
EndIf
EndIf
ProcedureReturn Gadget
EndProcedure
Procedure KnobControl_GetValue(Gadget)
; Return the Value of the 'Gadget'
Protected *KnobControl.KnobControlData
Protected value
*KnobControl = __KnobControl_Get__(Gadget)
If *KnobControl
value = *KnobControl\Value
EndIf
ProcedureReturn value
EndProcedure
Procedure KnobControl_SetValue(Gadget , Value)
; Set the Value of the 'Gadget'
; (convert value to angle)
Protected *KnobControl.KnobControlData
Protected angle.d
*KnobControl = __KnobControl_Get__(Gadget)
If *KnobControl
With *KnobControl
angle = (\MaxAngle - \MinAngle)
If angle And (\MaxValue - \MinValue)
*KnobControl\Angle = (Value - \MinValue) / ((\MaxValue - \MinValue) / angle) + \MinAngle
Else
*KnobControl\Angle = Value
EndIf
EndWith
__KnobControl_Update__(*KnobControl)
EndIf
EndProcedure
Procedure KnobControl_SetColor(Gadget , ColorType , Color)
; Set the Color (RGB) of the specified "ColorType"
Protected *KnobControl.KnobControlData
*KnobControl = __KnobControl_Get__(Gadget)
If *KnobControl
With *KnobControl
Select ColorType
Case #KnobControl_Background : \ColorBackGround = Color
Case #KnobControl_Foreground : \ColorForeGround = Color
Case #KnobControl_Border : \ColorBorder = Color
Case #KnobControl_Highlight : \ColorHighLight = Color
Case #KnobControl_Shadow : \ColorShadow = Color
EndSelect
EndWith
__KnobControl_Redraw__(*KnobControl)
EndIf
EndProcedure
Procedure KnobControl_Event(Gadget , Event)
; KnobControl event handling
; Return #True if 'Event' is valid
Protected *KnobControl.KnobControlData
Protected s,mx,my,angle,angleDif,redraw
Protected result = #False
*KnobControl = __KnobControl_Get__(Gadget)
If *KnobControl
With *KnobControl
mx = GetGadgetAttribute(\Canvas , #PB_Canvas_MouseX)
my = GetGadgetAttribute(\Canvas , #PB_Canvas_MouseY)
If Event = #PB_EventType_Focus
\HasFocus = #True
result = #True
ElseIf Event = #PB_EventType_LostFocus
\HasFocus = #False
__KnobControl_Update__(*KnobControl , #True)
ElseIf Event = #PB_EventType_LeftButtonUp
__KnobControl_Update__(*KnobControl , #True)
EndIf
If \HasFocus
If Event = #PB_EventType_LeftButtonDown
\LastAngle = Degree(ATan2(\Radius - mx , \Radius - my))
result = #True
ElseIf Event = #PB_EventType_MouseMove
If GetGadgetAttribute(\Canvas , #PB_Canvas_Buttons) = #PB_Canvas_LeftButton
angle = Degree(ATan2(\Radius - mx , \Radius - my))
angleDif = Mod(angle - \LastAngle , 360)
If angleDif > 180
angleDif - 360
ElseIf angleDif < -180
angleDif + 360
EndIf
\Angle + angleDif
\LastAngle = angle
result = #True
EndIf
ElseIf Event = #PB_EventType_MouseWheel
angleDif = (\MaxAngle - \MinAngle)
If angleDif And \Steps
\Angle + GetGadgetAttribute(\Canvas , #PB_Canvas_WheelDelta) * (angleDif / \Steps)
Else
\Angle + GetGadgetAttribute(\Canvas , #PB_Canvas_WheelDelta) * \Steps
EndIf
result = #True
EndIf
EndIf
EndWith
If result
__KnobControl_Update__(*KnobControl)
EndIf
ProcedureReturn result
EndIf
EndProcedure
Procedure KnobControl_Free(Gadget)
; free the CanvasGadget and the allocated memory
Protected *KnobControl.KnobControlData
*KnobControl = __KnobControl_Get__(Gadget)
If *KnobControl
FreeGadget(*KnobControl\Canvas)
FreeMemory(*KnobControl)
EndIf
EndProcedure
; - Knob-Control - Test -
Define event,current
OpenWindow(0,0,0,320,220,"KnobControl" , #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
StringGadget(0,60,190,200,20,"")
; Default Controller
KnobControl(1, 10,10,20)
; Speedometer ; Range 0 to 255 ; Stepsize 10 ; Anglge -90 to +90
KnobControl(2,100,10,35, 0,255, 10 , -90, 90 , #KnobControl_Ticks | #KnobControl_LinearPointer | #KnobControl_Smooth)
; Controller ; Range -1000 to +1000 ; Stepsize 20 ; Angle -90 to +810 (= 2.5 Rounds)
KnobControl(3,220,10,45, -1000,1000, 20,-90,810 , #KnobControl_Ticks)
; Clock with custom colors
KnobControl(4, 30,80,40, 1,12, 11, 30,360 , #KnobControl_Ticks|#KnobControl_Infinite | #KnobControl_LinearPointer | #KnobControl_Smooth)
KnobControl_SetColor(4 , #KnobControl_Foreground , RGB(100,180,110))
KnobControl_SetColor(4 , #KnobControl_Border , RGB(255,255,255))
KnobControl_SetColor(4 , #KnobControl_Highlight , RGB(100,225,0))
KnobControl_SetColor(4 , #KnobControl_Shadow , RGB(255,255,255))
; Infinte controller ; Stepsize 1
KnobControl(5, 150,110,25, 0,0,1,0,0,#KnobControl_Infinite)
AddWindowTimer(0,0,1000)
Repeat
event = WaitWindowEvent()
If event = #PB_Event_Gadget
Select EventGadget()
Case 1,2,3,4,5
If KnobControl_Event(EventGadget() , EventType())
current = EventGadget()
SetGadgetText(0 , "KnobControl " + Str(current) + " Value:" + Str(KnobControl_GetValue(current)))
EndIf
Case 0
If EventType() = #PB_EventType_Focus
SetGadgetText(0 , "")
ElseIf EventType() = #PB_EventType_Change
KnobControl_SetValue(current , Val(GetGadgetText(0)))
EndIf
EndSelect
ElseIf event = #PB_Event_Timer
KnobControl_SetValue(4 , KnobControl_GetValue(4) + 1)
EndIf
Until event = #PB_Event_CloseWindow
KnobControl_Free(1)
KnobControl_Free(2)
KnobControl_Free(3)
KnobControl_Free(4)
KnobControl_Free(5)