potentiomètre circulaire

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

potentiomètre circulaire

Message par GallyHC »

Bonjour,

Voila un potentiomètre circulaire, j'ai commencer le mouvement mais cela ne me convient pas. Au moins cela montre ce que cela donnera, une fois fini. Mais c'est encore en test et donc le code est pas très propre (voir sale).

Image

En gros je voudrais arriver a suivre le mouvement de la souris en rotation (mais la, j'y arrive pas encore).

Le code :

Code : Tout sélectionner

; +======================================================+
; |                                                      |
; +------------------------------------------------------+
; | COPYRIGHT(C)2007-2015, ALL RIGHT RESERVED KOAKDESIGN |
; +--------------+---------------------------------------+
; | Program/Vers | PUREBASIC 5.31                        |
; +--------------+---------------------------------------+
; | VER & REV    | 0.0.1                                 |
; +--------------+---------------------------------------+
; | Program name |                                       |
; +======================================================+

; +======================================================+
; | Original Version: 0.0.1                              |
; +--------------+---------------------------------------+
; | Created by   |                                       |
; | Graphix by   |                                       |
; +--------------+---------------------------------------+
; | Comments:    |                                       |
; +--------------+                                       |
; |                                                      |
; |                                                      |
; |                                                      |
; +======================================================+

; +======================================================+
; | Système d'Exploitation                               |
; +--------------+---------------------------------------+
; | Window       | Oui                                   |
; | Linux        | Oui                                   |
; | MacOS        | Oui                                   |
; +======================================================+

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

EnableExplicit

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Enumeration
  #Window
  #Canvas
EndEnumeration

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Global precalc.f = 2 * #PI / 360

Procedure.f GSin(angle.f)
; CALCUL DU PRECALCUL DES SINUS.
  ProcedureReturn Sin(angle * precalc) 
   
EndProcedure 

Procedure.f GCos(angle.f) 
; CALCUL DU PRECALCUL DES COSINUS.
  ProcedureReturn Cos(angle * precalc) 
  
EndProcedure

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Procedure ACircle(x.i, y.i, radius.d, antilenh.d, color.i)
;
  Define.l lR, lG, lB
  Define.d dNormal, dValue

  If radius <= 0
    radius = 0.00001
  EndIf
  If antilenh <= 0
    antilenh = 0.00001
  EndIf

  ResetGradientColors()
  DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient)

  lR      = Red  (color)
  lG      = Green(color)
  lB      = Blue (color)
  dNormal = 1 / radius
  dValue  = 1.0 - antilenh * dNormal

  GradientColor(   0  , RGBA(lR, lG, lB, 255))
  GradientColor(dValue, RGBA(lR, lG, lB, 255))
  GradientColor(   1  , RGBA(lR, lG, lB, 0  ))

  CircularGradient(x, y, radius)
  Circle          (x, y, radius)
  
EndProcedure

Procedure DrawValue(x.l, y.l, rayonx, rayony .l, segment.l, ilen.l, ldensity.l, value)
; ROUTINE DE TRACAGE D'UN CERCLE EN X SEGMENTS.
  Define i.l
  Define new_x.l
  Define new_y.l
  If segment < 4
    segment = 4
  EndIf
  
  DrawingMode(#PB_2DDrawing_Transparent)
  For i = 20 To 340 Step 20
    new_x = x + GSin(i + 180) * (rayonx - ilen)
    new_y = y - GCos(i + 180) * (rayony - ilen)
    If i < value
      ACircle(new_x,        new_y,        8, 8, RGB(255,0,0))
      ACircle(new_x,        new_y,        3, 2, RGB(0,0,0))
      ACircle(new_x,        new_y,        5, 2, RGB(255,0,0))
      ACircle(new_x,        new_y,        2, 2, RGB(255,100,100))
    Else
      ACircle(new_x,        new_y,        3, 2, RGB(0,0,0))
      ACircle(new_x,        new_y,        5, 2, RGB(100,0,0))
      ACircle(new_x,        new_y,        2, 2, RGB(200,0,0))
    EndIf
  Next i

EndProcedure

Procedure DrawCircular(WindowW, WindowH, x, y)
;  
  Define ircircle = WindowW / 7
  Define idensity = WindowW / 100
  
  Define dx = x  -  (WindowW * 0.5)
  Define dy = y  -  (WindowW * 0.5)
  Define F  = Degree(ATan2(dx, dy))
  
  Define new_x = (WindowW * 0.5) - GCos(F + 180) * ((ircircle * 2) - ircircle + 15)
  Define new_y = (WindowH * 0.5) - GSin(F + 180) * ((ircircle * 2) - ircircle + 15)
    
  F - 90
  If F < 0
    F = 360 + F
  EndIf
    
  StartDrawing(CanvasOutput(#Canvas))
    ;Box(0, 0, WindowW, WindowH, $f0f0f0)
    Box(0, 0, WindowW, WindowH, RGB(0,255,255))
    
    ACircle(WindowW*0.5,        WindowH*0.5,        WindowW * 0.5 - ircircle + 21, 2, RGB(0,0,0))
    ACircle(WindowW*0.5,        WindowH*0.5,        WindowW * 0.5 - ircircle + 20, 2, RGB(60,60,60))
        
    ACircle(WindowW*0.5 + 6,    WindowH*0.5 + 10,   WindowW * 0.5 - ircircle + 0, 2, RGB(50,50,50))
    ACircle(WindowW*0.5 + 4,    WindowH*0.5 + 8,    WindowW * 0.5 - ircircle + 0, 2, RGB(40,40,40))
    ACircle(WindowW*0.5 + 2,    WindowH*0.5 + 6,    WindowW * 0.5 - ircircle + 0, 2, RGB(30,30,30))
    
    DrawValue(WindowW*0.5,      WindowH*0.5,        WindowW * 0.5 - (ircircle / 2) + 9, WindowW * 0.5 - (ircircle / 2) + 9, 100, ircircle / 2, idensity, F)
    
    ACircle(WindowW*0.5,        WindowH*0.5,        WindowW * 0.5 - ircircle,     2, RGB(0,0,0))
    ACircle(WindowW*0.5,        WindowH*0.5,        WindowW * 0.5 - ircircle - 1, 2, RGB(255,255,255)) 
    ACircle(WindowW*0.5,        WindowH*0.5,        WindowW * 0.5 - ircircle - 3, 2, RGB(200,200,200)) 
    ACircle(WindowW*0.5,        WindowH*0.5,        WindowW * 0.5 - ircircle - 5, 2, RGB(230,230,230)) 
    
    ACircle(new_x,        new_y,        ircircle - 5, 2, RGB(0,0,0))
    ACircle(new_x,        new_y,        ircircle - 6, 2, RGB(160,160,160))
    ACircle(new_x,        new_y,        ircircle - 7, 2, RGB(180,180,180))
    ACircle(new_x,        new_y,        ircircle - 10, 2, RGB(200,200,200))
    
    StopDrawing()

EndProcedure

; ****************************************************************************
; ****************************************************************************
; ****************************************************************************
; ****************************************************************************

; +--------------------------------------------------------------------------+
; |                                                                          |
; +--------------------------------------------------------------------------+

Define.i event, eveng, evenp, WindowW = 200, WindowH = 200
  
If OpenWindow(#Window, 0, 0, WindowW, WindowH, "potentiomètre circulaire", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CanvasGadget(#Canvas, 0, 0, WindowW, WindowH, #PB_Canvas_Keyboard)
  
  DrawCircular(WindowW, WindowH, WindowW * 0.5, WindowH)
  
  Repeat
    
    event = WaitWindowEvent()
    evenp = EventType()
    eveng = EventGadget()
    
    If eveng = #Canvas
      ;Debug "pass"
      If evenp = #PB_EventType_MouseWheel
        ;Debug GetGadgetAttribute(#Canvas, #PB_Canvas_WheelDelta)
      EndIf
      If evenp = #PB_EventType_LeftButtonDown Or (evenp = #PB_EventType_MouseMove And GetGadgetAttribute(#Canvas, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
        DrawCircular(WindowW, WindowH, GetGadgetAttribute(#Canvas, #PB_Canvas_MouseX), GetGadgetAttribute(#Canvas, #PB_Canvas_MouseY))
      EndIf
    EndIf
    
  Until Event = #PB_Event_CloseWindow
EndIf
End
Cordialement,
GallyHC
Dernière modification par GallyHC le mar. 03/mars/2015 17:08, modifié 6 fois.
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: potentiomètre circulaire

Message par GallyHC »

Bonjour,

Un mouvement un peu plus sympa pour le potentiomètre. A vous de me dire (mis a vous premier post).

prochaine étape les leds et le refaire en un "vrai gadget".

GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: potentiomètre circulaire

Message par GallyHC »

Bonjour,

Quelque problème si des personnes peuvent me donner un coup de main. En gros le bouton en bas devrais être a 0 et je n'y arrive pas. Code mis a jour.

GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
venom
Messages : 3137
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: potentiomètre circulaire

Message par venom »

Salut GallyHC,

Désolé pas le temps de me pencher sur le code mais le résultat est top. Bravo, bonne continuation






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: potentiomètre circulaire

Message par GallyHC »

Bon voila mon test a pas trop mal avancer, à vous de me dire maintenant (Premier post mis a jour).

GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Raym
Messages : 4
Inscription : lun. 13/mai/2013 23:14

Re: potentiomètre circulaire

Message par Raym »

GallyHC a écrit :Bonjour,

Quelque problème si des personnes peuvent me donner un coup de main. En gros le bouton en bas devrais être a 0 et je n'y arrive pas. Code mis a jour.

GallyHC
Bonjour GallyHC, je ne sais pas si ma réponse corresponds à ce que tu cherches. Je part du fait que la résistance d'un potentiomètre varie par exemple de 0 à 100 Ohms. Il n' y a pas de lien continu. Ma solution est la suivante :

Code : Tout sélectionner

Procedure DrawValue(x.l, y.l, rayonx, rayony .l, segment.l, ilen.l, ldensity.l, value)
; ROUTINE DE TRACAGE D'UN CERCLE EN X SEGMENTS.
	Define i.l
	Define new_x.l
	Define new_y.l
	If segment < 4
		segment = 4
	EndIf
	
	DrawingMode(#PB_2DDrawing_Transparent)
; ===========
;ICI changement
	For i = 20 To 340  Step 16
; ===========
		
		new_x = x + GSin(i + 180) * (rayonx - ilen)
		new_y = y - GCos(i + 180) * (rayony - ilen)
		If i < value
			ACircle(new_x,        new_y,        8, 8, RGB(255,0,0))
			ACircle(new_x,        new_y,        3, 2, RGB(0,0,0))
			ACircle(new_x,        new_y,        5, 2, RGB(255,0,0))
			ACircle(new_x,        new_y,        2, 2, RGB(255,100,100))
		Else
			ACircle(new_x,        new_y,        3, 2, RGB(0,0,0))
			ACircle(new_x,        new_y,        5, 2, RGB(100,0,0))
			ACircle(new_x,        new_y,        2, 2, RGB(200,0,0))
		EndIf


	Next i

EndProcedure
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: potentiomètre circulaire

Message par Ar-S »

GallyHC a écrit :Bon voila mon test a pas trop mal avancer, à vous de me dire maintenant (Premier post mis a jour).
GallyHC
C'est vraiment plus fonctionnel qu'au début bien joué. Je suis géné par le fait de passer de 100 à 0 d'un coup par contre.
Il faudrait que le potar se bloque à 100 ou puisse seulement redescendre en sens anti horaire.
Idem pour passer de 0 à 100 d'un coup. Le potar devrait seulement pouvoir monter en sens horaire.

Le rendu graphique est vraiment classos pour du rendu code bravo.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: potentiomètre circulaire

Message par Micoute »

Bonjour GallyHC et bravo pour ton application qui est très 'réaliste', mais il faudrait que tu mettes des taquets pour éviter dépasser le maxi et inversement pour le mini, une petite condition suffira !

s'il fallait noter ton programme, je mettrais un 19,5/20.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: potentiomètre circulaire

Message par GallyHC »

Bonjour,

C'est prévus le blocage au maxi et au mini, mais bon c des test brut. Je n'arrivais pas a grand chose pour le mouvement a la souris et pour les leds. La sa fonctionne a peu près. Donc j'ai voulu montré.

GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
TazNormand
Messages : 1297
Inscription : ven. 27/oct./2006 12:19
Localisation : Calvados (14)

Re: potentiomètre circulaire

Message par TazNormand »

Bien joué GallyHC,

Le fait de bloquer le "potar" doit être une option, car ça peut être utile d'avoir un potar qui tourne sans blocage.

Encore Bravo!
Image
Image
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: potentiomètre circulaire

Message par Micoute »

Je suis d'accord avec TazNormand que je salue au passage, car on doit pouvoir choisir l'option que l'on souhaite et je t'invite à continuer ce travail excellent !
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: potentiomètre circulaire

Message par GallyHC »

Bonjour,

Je prend bonne note de vos remarques au sujet de ce code et j'en déduit au moins deux choses :

1. Le potentiomètre doit avoir un choix soit de rotation libre ou soit être bloquer au mini et maxi.
2. les leds peuvent être toujours être entre 0 et "100%" librement ou une fois au maxi (ou mini) ne pas pouvoir changer d'état (reste à 100% ou à 0%).

Je prend note, tout cela pour la réalisation du gadget final. Bon c'est a cette partie du code que je pèche, car je voudrais facilement pouvoir ajouter par la suite d'autre gadget de ma création (sachant que j'en ai déjà au moins deux a gérer, le linéaire et le circulaire). Je recherche une solution simple (déjà pour moi) et surtout que tout le monde puisse facilement ajouter ces propre gadget et que cela reste "propre" niveau code. Pas très simple à faire.

Sinon j'ai mis a jour le code (toujours en test) avec la proposition de "Raym", qui me parait juste (pour preuve avec ce que je peux utilisé une "BCF2000 de behringer") et ce qui m'a justement donné l'idée de faire ce code.

Encore merci pour vos encouragement,
GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
MLD
Messages : 1124
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

Re: potentiomètre circulaire

Message par MLD »

@ salut Gally

Super ton potar. Le linéaire était déja superbe.
Une petite idée: Pour des applications de précisions (genre radio amateur) ton potar ne pourrait'il pas faire 10 tours pour allumer toutes les leds et avoir la valeur max?. Un potar de précision quoi. :lol:
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

Re: potentiomètre circulaire

Message par GallyHC »

MLD > heu oui pourquoi pas a voir (surtout comment le faire ;)).

GallyHC
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: potentiomètre circulaire

Message par Micoute »

Bonsoir GallyHC, tu peux te référer à mon programme, tu verras il y a plusieurs sortes de boutons rotatifs.

Code : Tout sélectionner

; BoutonRotatif
; ----------------
; Mars 2012  M.L
;
;  clic gauche sur un bouton en maintenant le bouton enfoncé
; tourner le 'BoutonRotatif' à gauche ou à droite
;EnableExplicit

Structure DonneesBoutonRotatif
  Canvas.i
  
  Rayon.w   
  AngleMin.i
  AngleMax.i
  ValeurMin.i
  ValeurMax.i
  Etat.i
  Valeur.i
  Angle.i
  DernierAngle.i
  Pas.i
  Drapeaux.i
  A_le_Focus.b
  
  CouleurFond.i   
  CouleurPremierPlan.i
  CouleurBordure.i
  CouleurOmbre.i
  CouleurSurbrillante.i
EndStructure

Enumeration
  #BoutonRotatif_CoulFond
  #BoutonRotatif_PremPlan
  #BoutonRotatif_Bord
  #BoutonRotatif_Surbrillant
  #BoutonRotatif_Ombre
EndEnumeration

#BoutonRotatif_Tics               = 1      ; dessiner les tics autour du contrôle
#BoutonRotatif_PointeurLineaire   = 2      ; dessiner un pointeur linéaire au lieu d'un cercle
#BoutonRotatif_Infini             = 4      ; tournant à l'infini gauche ou à droite
#BoutonRotatif_Fluide             = 8      ; autoriser une circulation fluide

Declare BoutonRotatif(Gadget, x, y, Rayon, ValeurMin=0, ValeurMax=100, Pas=360, AngleMin=0, AngleMax=360 , Drapeaux=0)
Declare ObtenirValeur_BoutonRotatif(Gadget)
Declare DefinirValeur_BoutonRotatif(Gadget, Valeur)
Declare DefinirCouleur_BoutonRotatif(Gadget, TypeCouleur, Couleur)
Declare Evenement_BoutonRotatif(Gadget, Evenement)
Declare Liberer_BoutonRotatif(Gadget)

Procedure __Redessiner_BoutonRotatif__(*BoutonRotatif.DonneesBoutonRotatif)
  ; tous les trucs de dessin	
  Protected a,s,x,y,AngleMin,AngleMax
  
  If *BoutonRotatif
    StartDrawing(CanvasOutput(*BoutonRotatif\Canvas))
    With *BoutonRotatif
      Box(0,0,OutputWidth(), OutputHeight(), \CouleurFond)
      ; dessiner le 'cadran'
      Circle(\Rayon, \Rayon, \Rayon - 1, \CouleurBordure)
      DrawingMode(#PB_2DDrawing_Gradient)
      If \A_le_Focus
        GradientColor(0.0, \CouleurSurbrillante)
      Else
        GradientColor(0.0, \CouleurPremierPlan)            
      EndIf
      GradientColor(1.0, \CouleurOmbre)
      CircularGradient(\Rayon * 0.65, \Rayon * 0.65 , \Rayon * 3)
      Circle(\Rayon, \Rayon, \Rayon - 3)
      DrawingMode(#PB_2DDrawing_Default)
      If \Drapeaux & #BoutonRotatif_Tics
        ; dessiner les 'Tics'
        If \AngleMin Or \AngleMax
          AngleMin = \AngleMin - 90
          AngleMax = \AngleMax - 90
        Else
          AngleMin = 0
          AngleMax = 360
        EndIf
        If (AngleMax - AngleMin) And \Pas 
          a = AngleMin
          s = (AngleMax - AngleMin) / \Pas
          Repeat
            x = \Rayon - Cos(Radian(a)) * (\Rayon * 0.85)
            y = \Rayon - Sin(Radian(a)) * (\Rayon * 0.85)
            Circle(x, y, 1, \CouleurOmbre)
            a + s
          Until a > AngleMax Or a > (AngleMin + 360)
        EndIf
      EndIf
      ; dessiner l'aiguille de l'horloge
      x   = \Rayon - Cos(Radian(\Etat - 90)) * (\Rayon * 0.65)
      y   = \Rayon - Sin(Radian(\Etat - 90)) * (\Rayon * 0.65)
      If \Drapeaux & #BoutonRotatif_PointeurLineaire
        LineXY(\Rayon, \Rayon, x, y, \CouleurOmbre)
        LineXY(\Rayon + 1, \Rayon, x + 1, y, \CouleurOmbre)
        LineXY(\Rayon, \Rayon + 1, x, y + 1   , \CouleurOmbre)
        LineXY(\Rayon + 1, \Rayon + 1, x + 1, y + 1, \CouleurOmbre)
        Circle(\Rayon, \Rayon, 3, \CouleurOmbre)
        Circle(\Rayon, \Rayon, 1, \CouleurFond)
      Else            
        Circle(x, y, 3, \CouleurOmbre)
        Circle(x, y, 1, \CouleurPremierPlan)
      EndIf
    EndWith
    StopDrawing()
  EndIf
EndProcedure

Procedure __Mise_a_jour_BoutonRotatif__(*BoutonRotatif.DonneesBoutonRotatif, VerrouillerAngle = #False)
  ; Mise à jour Angle et Valeur
  
  Protected Angle.d, TaillePas
  
  If *BoutonRotatif
    With *BoutonRotatif
      If \Drapeaux & #BoutonRotatif_Infini = 0            
        ; agraffer l'Angle
        If \Angle < \AngleMin
          \Angle = \AngleMin
        ElseIf  \Angle > \AngleMax
          \Angle = \AngleMax
        EndIf         
      EndIf
      If \Pas
        Angle = (\AngleMax - \AngleMin)         
        TaillePas = Angle / \Pas
        If Angle And TaillePas
          ; convertir l'Angle en valeur
          If VerrouillerAngle Or (\Drapeaux & #BoutonRotatif_Fluide) = #False
            \Etat = Round(\Angle / (TaillePas * 1.0), #PB_Round_Nearest) * TaillePas
          Else
            \Etat = \Angle
          EndIf
          \Valeur = (\Etat - \AngleMin) * ((\ValeurMax - \ValeurMin) / Angle) + \ValeurMin
        Else
          If VerrouillerAngle Or (\Drapeaux & #BoutonRotatif_Fluide) = #False
            \Etat = Round(\Angle / (\Pas * 1.0), #PB_Round_Nearest) * \Pas
          Else
            \Etat = \Angle
          EndIf
          \Valeur = \Etat
        EndIf            
      EndIf
      If \ValeurMin Or \ValeurMax
        ; garder Valeur à l'intérieur de la fourchette
        If \Valeur > \ValeurMax
          \Valeur = Mod(\Valeur, \ValeurMax)
        EndIf
        If \Valeur < \ValeurMin
          \Valeur = Mod(\Valeur, \ValeurMax) + \ValeurMax
        EndIf            
      EndIf
    EndWith
    __Redessiner_BoutonRotatif__(*BoutonRotatif)
  EndIf
EndProcedure

Procedure __ObtenirValeurs_BoutonRotatif__(Gadget)
  ; Retourne les Donnees du Bouton Rotatif du 'Gadget' 
  
  If IsGadget(Gadget) = 0 Or GadgetType(Gadget) <> #PB_GadgetType_Canvas
    ProcedureReturn #Null
  EndIf
  ProcedureReturn GetGadgetData(Gadget)
EndProcedure

ProcedureDLL BoutonRotatif(Gadget, x, y, Rayon, ValeurMin=0, ValeurMax=100, Pas=360, AngleMin=0, 
                           AngleMax=360, Drapeaux=0)
  ; Crée un nouveau Bouton Rotatif et retourne son handle
  
  Protected *BoutonRotatif.DonneesBoutonRotatif
  *BoutonRotatif = __ObtenirValeurs_BoutonRotatif__(Gadget)
  If *BoutonRotatif
    ; si un bouton existe déjà avec cet ID - le supprimer
    Liberer_BoutonRotatif(Gadget)
  EndIf   
  If AngleMax < AngleMin
    Swap AngleMin, AngleMax
  EndIf
  If ValeurMax < ValeurMin
    Swap ValeurMin, ValeurMax
  EndIf
  If Gadget = #PB_Any
    Gadget = CanvasGadget(#PB_Any, x, y, Rayon * 2, Rayon * 2, #PB_Canvas_Keyboard)
  Else
    CanvasGadget(Gadget, x, y, Rayon * 2, Rayon * 2 , #PB_Canvas_Keyboard)
  EndIf
  If IsGadget(Gadget)
    *BoutonRotatif = AllocateMemory(SizeOf(DonneesBoutonRotatif))
    If *BoutonRotatif
      With *BoutonRotatif
        \Canvas    = Gadget
        \AngleMin  = AngleMin
        \AngleMax  = AngleMax
        \ValeurMin = ValeurMin
        \ValeurMax = ValeurMax
        \Angle     = AngleMin
        ;\Etat      = ValeurMin         
        \Rayon     = Rayon
        \Drapeaux  = Drapeaux         
        \Pas       = Pas
        If \Pas < 1
          \Pas     = 1
        EndIf
        CompilerIf #PB_Compiler_OS = #PB_OS_Windows
          \CouleurFond = GetSysColor_(#COLOR_3DFACE)
          \CouleurPremierPlan  = GetSysColor_(#COLOR_3DLIGHT)
          \CouleurSurbrillante = GetSysColor_(#COLOR_3DHIGHLIGHT)
          \CouleurBordure      = GetSysColor_(#COLOR_3DSHADOW)
          \CouleurOmbre        = GetSysColor_(#COLOR_3DDKSHADOW)
        CompilerElse
          \CouleurFond         = $F2F1F0
          \CouleurPremierPlan  = $C8D0D4
          \CouleurSurbrillante = $FFFFFF
          \CouleurBordure      = $808080
          \CouleurOmbre         = $404040
        CompilerEndIf
      EndWith
      SetGadgetData(Gadget, *BoutonRotatif)
      __Mise_a_jour_BoutonRotatif__(*BoutonRotatif)
    Else
      FreeGadget(Gadget)
      Gadget = 0
    EndIf
  EndIf
  ProcedureReturn Gadget
EndProcedure

ProcedureDLL ObtenirValeur_BoutonRotatif(Gadget)
  ; Retourne la Valeur du 'Gadget'	
  Protected *BoutonRotatif.DonneesBoutonRotatif
  Protected Valeur
  
  *BoutonRotatif = __ObtenirValeurs_BoutonRotatif__(Gadget)
  
  If *BoutonRotatif
    Valeur = *BoutonRotatif\Valeur
  EndIf
  ProcedureReturn Valeur
EndProcedure

ProcedureDLL DefinirValeur_BoutonRotatif(Gadget , Valeur)
  ; Définit la Valeur du 'Gadget'
  ; (convertit Valeur en Angle)	
  Protected *BoutonRotatif.DonneesBoutonRotatif
  Protected Angle.d
  
  *BoutonRotatif = __ObtenirValeurs_BoutonRotatif__(Gadget)
  
  If *BoutonRotatif
    With *BoutonRotatif
      Angle = (\AngleMax - \AngleMin)
      If Angle And (\ValeurMax - \ValeurMin)
        *BoutonRotatif\Angle = (Valeur - \ValeurMin) / ((\ValeurMax - \ValeurMin) / Angle) + \AngleMin
      Else
        *BoutonRotatif\Angle = Valeur
      EndIf
    EndWith
    __Mise_a_jour_BoutonRotatif__(*BoutonRotatif)
  EndIf
EndProcedure

ProcedureDLL DefinirCouleur_BoutonRotatif(Gadget, TypeCouleur, Couleur)
  ; Définit la Couleur (RGB) du "TypeCouleur" spécifié	
  Protected *BoutonRotatif.DonneesBoutonRotatif
  
  *BoutonRotatif = __ObtenirValeurs_BoutonRotatif__(Gadget)
  
  If *BoutonRotatif
    With *BoutonRotatif
      Select TypeCouleur
        Case #BoutonRotatif_CoulFond   :   \CouleurFond         = Couleur
        Case #BoutonRotatif_PremPlan   :   \CouleurPremierPlan  = Couleur
        Case #BoutonRotatif_Bord       :   \CouleurBordure      = Couleur
        Case #BoutonRotatif_Surbrillant:   \CouleurSurbrillante = Couleur
        Case #BoutonRotatif_Ombre      :   \CouleurOmbre        = Couleur
      EndSelect
    EndWith
    __Redessiner_BoutonRotatif__(*BoutonRotatif)
  EndIf
EndProcedure

ProcedureDLL Evenement_BoutonRotatif(Gadget, Evenement)
  ; BoutonRotatif gestion des évènements
  ; Retourne #True si 'Evenement' est valide	
  Protected *BoutonRotatif.DonneesBoutonRotatif
  Protected s, mx, my, Angle, AngleDif, Redessiner
  Protected Resultat = #False
  
  *BoutonRotatif = __ObtenirValeurs_BoutonRotatif__(Gadget)
  
  If *BoutonRotatif
    With *BoutonRotatif
      mx = GetGadgetAttribute(\Canvas, #PB_Canvas_MouseX)
      my = GetGadgetAttribute(\Canvas, #PB_Canvas_MouseY)
      If Evenement = #PB_EventType_Focus
        \A_le_Focus = #True
        Resultat = #True
      ElseIf Evenement = #PB_EventType_LostFocus
        \A_le_Focus = #False
        __Mise_a_jour_BoutonRotatif__(*BoutonRotatif, #True)
      ElseIf Evenement = #PB_EventType_LeftButtonUp
        __Mise_a_jour_BoutonRotatif__(*BoutonRotatif, #True)
      EndIf
      If \A_le_Focus
        If Evenement = #PB_EventType_LeftButtonDown
          \DernierAngle = Degree(ATan2(\Rayon - mx, \Rayon - my))
          Resultat = #True
        ElseIf Evenement = #PB_EventType_MouseMove
          If GetGadgetAttribute(\Canvas, #PB_Canvas_Buttons) = #PB_Canvas_LeftButton
            Angle    = Degree(ATan2(\Rayon - mx, \Rayon - my))                  
            AngleDif = Mod(Angle - \DernierAngle, 360)
            If AngleDif > 180
              AngleDif - 360
            ElseIf AngleDif < -180
              AngleDif + 360
            EndIf
            \Angle + AngleDif
            \DernierAngle =  Angle
            Resultat = #True
          EndIf
        ElseIf Evenement = #PB_EventType_MouseWheel
          AngleDif = (\AngleMax - \AngleMin)
          If AngleDif And \Pas         
            \Angle + GetGadgetAttribute(\Canvas, #PB_Canvas_WheelDelta) * (AngleDif / \Pas)
          Else
            \Angle + GetGadgetAttribute(\Canvas, #PB_Canvas_WheelDelta) * \Pas
          EndIf
          Resultat = #True
        EndIf
      EndIf
    EndWith
    
    If Resultat
      __Mise_a_jour_BoutonRotatif__(*BoutonRotatif)
    EndIf
    ProcedureReturn Resultat
  EndIf
EndProcedure

ProcedureDLL Liberer_BoutonRotatif(Gadget)
  ; libère le CanvasGadget et la mémoire allouée	
  Protected *BoutonRotatif.DonneesBoutonRotatif
  
  *BoutonRotatif = __ObtenirValeurs_BoutonRotatif__(Gadget)
  
  If *BoutonRotatif
    FreeGadget(*BoutonRotatif\Canvas)
    FreeMemory(*BoutonRotatif)
  EndIf
EndProcedure



CompilerIf #PB_Compiler_IsMainFile
  ; - Test - Bouton Rotatif -
  Enumeration
    #fenetre_principale
  EndEnumeration
  
  Enumeration
    #Defaut
    #Vitesse
    #Gamme
    #Horloge
    #Infini
    #Chaine
    #Texte
  EndEnumeration
  
  Define Evenement,BoutonCourant
  
  OpenWindow(#fenetre_principale,0,0,770,220,"BoutonRotatif" , #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  StringGadget(#Chaine,280,190,200,20,"")
  TextGadget(#Texte, 10, 160, 750, 20, "clic gauche sur un bouton en maintenant le bouton enfoncé tourner le 'BoutonRotatif' à gauche ou à droite",#PB_Text_Center)
  
  ; Bouton par défaut
  BoutonRotatif(#Defaut, 10,10,70)
  ;BoutonRotatif(#Defaut, 10,10,70,0,100,360,90,450) ; 90 pour mettre le zero à gauche
  
  ; Compteur de vitesse; Plage de 0 à 255; TaillePas 10; Angle -90 à 90 ; rajouter 180
  BoutonRotatif(#Vitesse,160,10,70, 0,250, 10 , 90, 270 , #BoutonRotatif_Tics | #BoutonRotatif_PointeurLineaire | #BoutonRotatif_Fluide)
  
  ; Bouton; Gamme de -1000 à 1000; TaillePas 20; Angle -90 à 810 (= 2,5 tours)
  BoutonRotatif(#Gamme,310,10,70, -1000,1000, 20,-90,810 , #BoutonRotatif_Tics)
  
  ; Horloge avec Couleurs personnalisées ; ajouter 180 pour redresser les aiguilles dans le bon sens
  BoutonRotatif(#Horloge, 460,10,70, 1,60, 11, 180,510 , #BoutonRotatif_Tics|#BoutonRotatif_Infini | #BoutonRotatif_PointeurLineaire | #BoutonRotatif_Fluide)
  DefinirCouleur_BoutonRotatif(#Horloge , #BoutonRotatif_PremPlan , RGB(100,180,110))
  DefinirCouleur_BoutonRotatif(#Horloge , #BoutonRotatif_Bord , RGB(255,255,255))
  DefinirCouleur_BoutonRotatif(#Horloge , #BoutonRotatif_Surbrillant , RGB(100,225,0))
  DefinirCouleur_BoutonRotatif(#Horloge , #BoutonRotatif_Ombre , RGB(255,255,255))
  
  ; Bouton Infini; TaillePas 1
  BoutonRotatif(#Infini, 610,10,70, 0,0,1,90,90,#BoutonRotatif_Infini)
  
  AddWindowTimer(0,0,1000)
  
  Repeat
    
    Evenement = WaitWindowEvent()
    
    If Evenement = #PB_Event_Gadget
      Select EventGadget()
        Case #Defaut,#Vitesse,#Gamme,#Horloge,#Infini
          If Evenement_BoutonRotatif(EventGadget() , EventType())
            BoutonCourant = EventGadget()
            SetGadgetText(#Chaine , "BoutonRotatif " + Str(BoutonCourant) + "  Valeur:" + Str(ObtenirValeur_BoutonRotatif(BoutonCourant)))
          EndIf
        Case #Chaine
          If EventType() = #PB_EventType_Focus
            SetGadgetText(#Chaine , "")
          ElseIf EventType() = #PB_EventType_Change
            DefinirValeur_BoutonRotatif(BoutonCourant , Val(GetGadgetText(#Chaine)))
          EndIf
      EndSelect
    ElseIf Evenement = #PB_Event_Timer
      DefinirValeur_BoutonRotatif(#Horloge , ObtenirValeur_BoutonRotatif(#Horloge) + 1)
    EndIf
    
  Until Evenement = #PB_Event_CloseWindow
  
  Liberer_BoutonRotatif(#Defaut)
  Liberer_BoutonRotatif(#Vitesse)
  Liberer_BoutonRotatif(#Gamme)
  Liberer_BoutonRotatif(#Horloge)
  Liberer_BoutonRotatif(#Infini)
CompilerEndIf
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Répondre