KnobControl (ehem. ControllerGadget)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Mr.L
Beiträge: 51
Registriert: 05.02.2011 21:04

KnobControl (ehem. ControllerGadget)

Beitrag von Mr.L »

Die Möglichkeiten des CanvasGadget sind ja praktisch unendlich... (Kann-was-Gadget :lol: )
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)
[/size]
Zuletzt geändert von Mr.L am 19.03.2012 19:48, insgesamt 2-mal geändert.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ControllerGadget

Beitrag von STARGÅTE »

Cool :allright:

mir gefällt vorallem, dass man mehrer Runden drehen kann, halt wie in "echt".
Ich habe zwar aktuell keinen Einsatz dafür, aber es kann hier und da das Spin-Gadget ersetzen

Es bietet eine schöne alternative zu meinem AngleGadget.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: ControllerGadget

Beitrag von ts-soft »

:allright:
Gefällt mir auch das GAUGE-Control :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: ControllerGadget

Beitrag von RSBasic »

Gefällt mir auch. Schaut gut aus. :allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: ControllerGadget

Beitrag von Nino »

Gefällt mir auch, aber der Name sollte besser geändert werden (wie ts-soft schon angedeutet hat).
Mr.L
Beiträge: 51
Registriert: 05.02.2011 21:04

Re: ControllerGadget

Beitrag von Mr.L »

So wie ich das sehe, ist das Gauge-Control eine runde Anzeige,
wo hingegen mein ControllerGadget ein interaktiver Regler ist (und auch eine Anzeige).
Aber hauptsache es gefällt :D
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: ControllerGadget

Beitrag von Nino »

Mr.L hat geschrieben:So wie ich das sehe, ist das Gauge-Control eine runde Anzeige,
"Gauge-Control" halte auch ich hier nicht für passend.
Mr.L hat geschrieben:wo hingegen mein ControllerGadget ein interaktiver Regler ist (und auch eine Anzeige).
Ich würde es als "Drehregler" bezeichnen (keine Ahnung, wie das auf Englisch heißt).

Grüße, Nino
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: ControllerGadget

Beitrag von RSBasic »

Ich denke einfach mal Knob Control? Wie z.B.: http://www.codeproject.com/Articles/256 ... ms-and-GDI
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: ControllerGadget

Beitrag von ts-soft »

Genau, Knop ist der richtige Begriff, bin ich nicht drauf gekommen.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Mr.L
Beiträge: 51
Registriert: 05.02.2011 21:04

Re: ControllerGadget

Beitrag von Mr.L »

STARGÅTE hat geschrieben:Es bietet eine schöne alternative zu meinem AngleGadget.
Dein AngleGadget kannte ich noch garnicht, es ist aber schon Interessant, wieviele Ähnlichkeiten zwischen unseren Programmen bestehen.
Antworten