Ecran de veille : Horloge analogique 24h.

Programmation d'applications complexes
Avatar de l’utilisateur
plabouro472
Messages : 53
Inscription : sam. 23/juil./2022 10:17

Ecran de veille : Horloge analogique 24h.

Message par plabouro472 »

Bonjour à tous,

Voici une horloge originale que j’affectionne tout particulièrement.
C'est un écran de veille qui utilise le module "ScreenSaver.pb" publié précédemment .

C'est avec grand plaisir que Je la partage.

Compilez en la nomant "Horloge 24h.exe" et remplacer ".exe" par ".scr" puis clic gauche sur "Horloge 24h.scr" et installer
C'est tout.

Code : Tout sélectionner


; Horloge analogique 24h pour un tour de cadran avec deux aiguilles.
; Une seule aiguille pour les heures et une trotteuse.
; Windows 11
; PB 6.40

;-Module ScreenSaver
;{ Version 20260628
DeclareModule ScreenSaver
 ; ******** Constantes et variables Publiques ***************
 
 
 ; ******** Declaration des procedures Publiques ***************
 Declare .a CheckStatus     ( )
 Declare   Start        ( saverName.s )
 Declare   Stop        ( )
 Declare .i GetWinSaver     ( )
 Declare .i GetWinPreview    ( )
 Declare .a IsScreenSaverMode  ( )
 Declare .s GetParameter    ( ) 
 Declare .f GetRatioX      ( )
 Declare .f GetRatioY      ( )
EndDeclareModule

Module    ScreenSaver
 ; ******** Constantes et variables privées ***************
 Enumeration
  #ScreenSaverMode
  #PreviewMode
 EndEnumeration
 
 Global width    .l
 Global height   .l
 Global RatioX   .f
 Global RatioY   .f
 Global SaverMode  .b
 Global previewWndHandleStr$ = ""
 
 ; ******** Procedures Privées ***************
 
 
 
 ; ******** Procedures Publiques ************
 ;************************************************************************************
 ; Garantit qu'une seule instance du programme sera lancée
 ; Parameters: Nom de l'économiseur (utilisé pour nommer le mutex)
 ;************************************************************************************
 Procedure Start(saverName.s)
  Shared OnlyOneStartMutex.l
  Protected OnlyOneStartError.l
  *MutexName = @saverName
  OnlyOneStartMutex = CreateMutex_(0, 1, *MutexName)
  OnlyOneStartError = GetLastError_()
  If OnlyOneStartMutex <> 0 And OnlyOneStartError = 0
   ProcedureReturn 1
  Else
   CloseHandle_(OnlyOneStartMutex)
   End
  EndIf
 EndProcedure
 
 
 ;************************************************************************************
 ; Libérer le mutex pour permettre le lancement d'une autre instance
 ;************************************************************************************
 Procedure Stop()
  SystemParametersInfo_ ( #SPI_SCREENSAVERRUNNING , 0 , @oldval , 0 ) ; Indiquez au système que l'économiseur d'écran n'est plus en fonction
  CloseHandle_(OnlyOneStartMutex)
 EndProcedure
 
 
 ;************************************************************************************
 ; En mode économiseur d'écran, recherchez toute action de l'utilisateur
 ; Return-Value: 1 si quelque chose a bougé depuis la dernière boucle
 ;************************************************************************************
 Procedure .a CheckStatus      ( )
  If saverMode = #ScreenSaverMode
   ExamineKeyboard() : ExamineMouse()
   If MouseDeltaX() Or MouseDeltaY() Or KeyboardPushed(#PB_Key_All) Or MouseButton(#PB_MouseButton_Left) Or MouseButton(#PB_MouseButton_Right)
    ProcedureReturn 1
   EndIf
   If  GetActiveWindow() = ScreenID()
    ProcedureReturn 1
   EndIf
  EndIf
  
  ProcedureReturn 0
 EndProcedure
 
 ;************************************************************************************
 ; Passe en mode Ecran de veille et en informe Windows
 ; Return-Value: Identifiant de la fenêtre créée en mode plein écran
 ;************************************************************************************
 Procedure .i GetWinSaver      ( )
  saverMode = #ScreensaverMode
  SystemParametersInfo_  ( #SPI_SCREENSAVERRUNNING , 1 , @oldval , 0 )
  ExamineDesktops     (  )
  RatioX   = 1.0
  RatioY   = 1.0
  ProcedureReturn OpenWindow ( #PB_Any , 0 , 0 , DesktopWidth( 0 )  , DesktopHeight( 0 )  , "" , #PB_Window_BorderLess  ) 
 EndProcedure
 
 ;************************************************************************************
 ; Passe en mode previsualisation et crée une fenêtre fille
 ; Return-Value: Identifiant de la fenêtre créée en mode previsualisation
 ;************************************************************************************
 Procedure .i GetWinPreview     ( )
  saverMode   = #PreviewMode
  DisplayHwnd  = Val ( previewWndHandleStr$ )
  GetClientRect_ ( DisplayHwnd , @PSize.RECT )
  width     = PSize\right
  height    = PSize\bottom
  ExamineDesktops     (  )
  RatioX    = width  / DesktopWidth ( 0 )
  RatioY    = height / DesktopHeight ( 0 )
  ProcedureReturn OpenWindow ( #PB_Any , 0 , 0 , width , height , "" , #WS_CHILD ,  DisplayHwnd )
 EndProcedure
 
 ;************************************************************************************
 ; Teste si l'on se trouve en mode Ecran de veille
 ; Return-Value: 1 si oui, 0 si non
 ;************************************************************************************
 Procedure .a IsScreenSaverMode   ( )
  ProcedureReturn Bool( SaverMode = #ScreenSaverMode )
 EndProcedure
 
; ***************************************************************
; Pour prévisualiser l'écran de veille Windows lance l'application
; en lui passant -P, /P ou P en premier paramètre.
;
; Pour la configuration, les paramètres sont par exemple -> /C:3606164
; Le second paramètre est le Handle de la fenêtre dans laquelle doit s'afficher l'écran de veille.
;
; Les paramètres peuvent commencer par un - ou un / 
; Entre le premier et le deuxième paramètre il peut y avoir un deux-points ou un espace.
; S'ils sont connectés par deux points, PB ne le reconnaît pas comme deux paramètres, et enregistre les deux dans Parametre1
; ***************************************************************
 Procedure .s GetParameter      ( )
  Protected .s Parameter$ =  ProgramParameter( 0 )
  If Len( Parameter$ ) > 2   ; Deux paramètres en un "/C:3606164"
   previewWndHandleStr$ = RemoveString ( Parameter$  , Left( Parameter$ , 3 ) , 1 )
   Parameter$      = RemoveString ( Parameter$  , Left( Parameter$ , 1 ) , 1 )
   Parameter$      = Left     ( Parameter$  , 1 )
   
  Else            ; Deux paramètres séparé -> /p /12345
   If Len( Parameter$ ) > 1
    Parameter$      = RemoveString ( Parameter$  , Left( Parameter$ , 1 ) , 1 )
   EndIf
   previewWndHandleStr$ = ProgramParameter( 1 )
   If FindString ( previewWndHandleStr$ , "-" , 0 ) <> 0 : previewWndHandleStr$ = RemoveString ( previewWndHandleStr$ , "-" , 1 ) : EndIf
   If FindString ( previewWndHandleStr$ , "/" , 0 ) <> 0 : previewWndHandleStr$ = RemoveString ( previewWndHandleStr$ , "/" , 1 ) : EndIf
   
  EndIf
  
  ProcedureReturn Parameter$
 EndProcedure
 
 ;************************************************************************************
 ; Calcule le facteur d'échelle
 ; Un GetWinSaver() ou GetWinPreview() doit être appelé.
 ; Return-Value: Le raport de la fenêtre retournée par rapport au plein écran
 ;************************************************************************************
 Procedure .f GetRatioX        ( )
  ProcedureReturn RatioX
 EndProcedure
 Procedure .f GetRatioY        ( )
  ProcedureReturn RatioY 
 EndProcedure

; ******* Initialisation *******
 InitKeyboard ( )
 InitMouse   ( )

EndModule
;}


;-Obj Horloge Analogique 24h
;{ Version 20260628
;
; L'horloge s'ajuste dans une Window, une ImageGadget ou un CanvasGadget
; elle s'adaptera automatiquement aux dimensions de celle-ci.
; Win_0          = OpenWindow  ( #PB_Any , #PB_Ignore , #PB_Ignore , 300         , 200         , Titre , Option )
;
; ImageHorlogeAnalogique = ImageGadget  ( #PB_Any , 0      , 0      , WindowWidth(Win_0) , WindowHeight(Win_0) , 0 )
; ImageHorlogeAnalogique  = CanvasGadget ( #PB_Any , 0      , 0      , WindowWidth(Win_0) , WindowHeight(Win_0)   )
; ImageHorlogeAnalogique = Win_0

Interface NewObj_Horloge
 NewAiguille     ( Typ.s                )
 AddPointAiguille  ( Typ.s , Dx.w  , Dy.w       )
 AddPointFill    ( Typ.s , Dx.w  , Dy.w        )
 SetColor      ( Typ.s , Coul.i           )
 SetTime       ( Time.q               )
 SetTexte      ( Nom.s , Dx.w  , Dy.w  , Txt.s  )
 SetFont       ( Txt.s , Dh.a  , Styl.i      )
 SetSens       ( SensRot.b              )
 Free        (                   )
EndInterface

Enumeration GadgetTyp
 #PL_GadgetType_Canvas
 #PL_GadgetType_Image
 #PL_GadgetType_Screen
EndEnumeration

Structure Coordonnee
 x    .w
 y    .w
 Ray   .f
 Arg   .f
EndStructure

Structure Texte
 x    .w
 y    .w
 Txt   .s
EndStructure

Structure Obj_Horloge_Typ
 *DSVT
 
 Diametre       .f
 Rayon         .f
 RadParSeconde_H    .f
 ;RadParSeconde_M    .f
 RadParSeconde_S    .f
 RadParSeconde     .f
 Sens         .f
 
 Couleur_H       .l
 ;Couleur_M       .l
 Couleur_S       .l
 CouleurFond      .l
 CouleurRepereCadran  .l
 
 NbPointAigui     .a ; Nombre maxi de coordonnées.
 
 NbPointAigui_H    .b
 ;NbPointAigui_M    .b
 NbPointAigui_S    .b
 
 NbPointFill_H     .b
 ;NbPointFill_M     .b
 NbPointFill_S     .b
 
 Remplissage_H     .b
 ;Remplissage_M     .b
 Remplissage_S     .b
 
 
 GadgetTyp       .a
 GadgetImage      .i
 CadranFond      .i
 CadranHorloge     .i
 
 DimX         .l
 DimY         .l
 RayonMini       .w
 RayonMaxi       .w
 RayonUnit       .w
 RayonMini_S      .w
 RayonMaxi_S      .w
 RayonUnit_S      .w
 
 OldSec        .u
 
 Police        .i
 PoliceStyle      .i
 PoliceTxt       .s
 
 TexteH        .a
 
 
 Array FillHeure    .Coordonnee ( 1 )
 ;Array FillMinute   .Coordonnee ( 1 )
 Array FillSeconde   .Coordonnee ( 1 )
 
 Array AiguilleHeure  .Coordonnee ( 1 )
 ;Array AiguilleMinute .Coordonnee ( 1 )
 Array AiguilleSeconde .Coordonnee ( 1 )
 
 Map  MapTexte    .Texte   (  )
 
EndStructure

; Procedures Privees
Procedure .f GetAngleRad           ( Dx.f  , Dy.f  )
 Protected .f ValTmp
 
 ValTmp = ATan2( Dx, Dy)
 If ValTmp < 0 : ValTmp + ( 2* #PI ) : EndIf
 ProcedureReturn ValTmp
EndProcedure
Procedure .f GetModule            ( Dx.f  , Dy.f  )
 ProcedureReturn Sqr( Dx*Dx + Dy*Dy )
EndProcedure
Procedure .w GetCoordX            ( Modul.f , Argum.f )
 ProcedureReturn Modul * Cos( Argum )
EndProcedure
Procedure .w GetCoordY            ( Modul.f , Argum.f )
 ProcedureReturn Modul * Sin( Argum )
EndProcedure

Procedure   Obj_Horloge_CalcPtsAiguille   ( *This.Obj_Horloge_Typ , Rad_H.f , Rad_M.f , Rad_S.f )
 Protected .i i
 With *This
  For i = 0 To \NbPointAigui_H
   \AiguilleHeure( i )\x   = GetCoordX( \AiguilleHeure  ( i )\Ray , \AiguilleHeure  ( i )\Arg + Rad_H  )
   \AiguilleHeure( i )\y   = GetCoordY( \AiguilleHeure  ( i )\Ray , \AiguilleHeure  ( i )\Arg + Rad_H  )
  Next
  For i = 0 To \NbPointFill_H
   \FillHeure( i )\x     = GetCoordX( \FillHeure    ( i )\Ray , \FillHeure    ( i )\Arg + Rad_H  )
   \FillHeure( i )\y     = GetCoordY( \FillHeure    ( i )\Ray , \FillHeure    ( i )\Arg + Rad_H  )
  Next
  
  ;For i = 0 To \NbPointAigui_M
  ; \AiguilleMinute( i )\x  = GetCoordX( \AiguilleMinute ( i )\Ray , \AiguilleMinute  ( i )\Arg + Rad_M  )
  ; \AiguilleMinute( i )\y  = GetCoordY( \AiguilleMinute ( i )\Ray , \AiguilleMinute  ( i )\Arg + Rad_M  )
  ;Next
  ;For i = 0 To \NbPointFill_M
  ; \FillMinute( i )\x    = GetCoordX( \FillMinute   ( i )\Ray , \FillMinute    ( i )\Arg + Rad_M  )
  ; \FillMinute( i )\y    = GetCoordY( \FillMinute   ( i )\Ray , \FillMinute    ( i )\Arg + Rad_M  )
  ;Next
  
  For i = 0 To \NbPointAigui_S
   \AiguilleSeconde( i )\x  = GetCoordX( \AiguilleSeconde ( i )\Ray , \AiguilleSeconde ( i )\Arg + Rad_S )
   \AiguilleSeconde( i )\y  = GetCoordY( \AiguilleSeconde ( i )\Ray , \AiguilleSeconde ( i )\Arg + Rad_S )
  Next
  For i = 0 To \NbPointFill_S
   \FillSeconde( i )\x    = GetCoordX( \FillSeconde   ( i )\Ray , \FillSeconde   ( i )\Arg + Rad_S  )
   \FillSeconde( i )\y    = GetCoordY( \FillSeconde   ( i )\Ray , \FillSeconde   ( i )\Arg + Rad_S  )
  Next
  
 EndWith
 
EndProcedure
Procedure   Obj_Horloge_DessineAiguille   ( *This.Obj_Horloge_Typ )
 Protected .i i
 Protected .w X  , Y , Dx , Dy
 
 With *This
  ;   FreeImage( \CadranHorloge )
  ;   \CadranHorloge = CopyImage  ( \CadranFond , #PB_Any )
  ;   StartDrawing ( ImageOutput( \CadranHorloge ) )
  SetOrigin   ( \DimX / 2 , \DimY / 2 )       ; Place l'origine du tracé
  DrawingMode( #PB_2DDrawing_Outlined )
  
  If MapSize( \MapTexte() )              ; 20250707
   FrontColor  ( \CouleurFond     )      ; 20250707
   BackColor   ( \CouleurRepereCadran )      ; 20250707
   DrawingFont  ( \Police )             ; 20250707
   ForEach \MapTexte( )
    X  =  \Rayon * \MapTexte()\x / 100        ; 20250707
    Y  = -\Rayon * \MapTexte()\y / 100        ; 20250707
    Dx = TextWidth ( \MapTexte()\Txt ) / 2      ; 20250707
    Dy = TextHeight( \MapTexte()\Txt ) / 2      ; 20250707
    DrawText( X - Dx , Y - Dy , \MapTexte()\Txt )  ; 20250707
   Next
  EndIf                        ; 20250707
  
  ; Dessinne la seconde
  FrontColor( \Couleur_S )
  If \NbPointAigui_S > 0    ; Si l'Aiguille a plusieurs points
   For i = 0 To \NbPointAigui_S - 1
    LineXY( \AiguilleSeconde( i )\x , -\AiguilleSeconde( i )\y , \AiguilleSeconde( i + 1 )\x , -\AiguilleSeconde( i + 1 )\y )
   Next
  ElseIf \NbPointAigui_S = 0  ; Si l'Aiguille a un seul point
   Circle ( \AiguilleSeconde( 0 )\x , -\AiguilleSeconde( 0 )\y , \RayonUnit )
  EndIf
  If \Remplissage_S = #True
   For i = 0 To \NbPointFill_S
    FillArea( \FillSeconde( i )\x , -\FillSeconde( i )\y , \Couleur_S )
   Next
  EndIf
  
;   ; Dessinne la minute
;   FrontColor( \Couleur_M )
;   If \NbPointAigui_M > 0    ; Si l'Aiguille a plusieurs points
;    For i = 0 To \NbPointAigui_M - 1
;     LineXY( \AiguilleMinute( i )\x , -\AiguilleMinute( i )\y , \AiguilleMinute( i + 1 )\x , -\AiguilleMinute( i + 1 )\y )
;    Next
;   ElseIf \NbPointAigui_M = 0  ; Si l'Aiguille a un seul point
;    Circle ( \AiguilleMinute( 0 )\x , -\AiguilleMinute( 0 )\y , \RayonUnit )
;   EndIf
;   If \Remplissage_M  = #True
;    For i = 0 To \NbPointFill_M
;     FillArea( \FillMinute( i )\x , -\FillMinute( i )\y , \Couleur_M )
;    Next
;   EndIf
  
  ; Dessinne l'heure
  FrontColor( \Couleur_H )
  If \NbPointAigui_H > 0    ; Si l'Aiguille a plusieurs points
   For i = 0 To \NbPointAigui_H - 1
    LineXY( \AiguilleHeure( i )\x , -\AiguilleHeure( i )\y , \AiguilleHeure( i + 1 )\x , -\AiguilleHeure( i + 1 )\y )
   Next
  ElseIf \NbPointAigui_H = 0  ; Si l'Aiguille a un seul point
   Circle ( \AiguilleHeure( 0 )\x , -\AiguilleHeure( 0 )\y , \RayonUnit )
  EndIf
  If \Remplissage_H  = #True
   For i = 0 To \NbPointFill_H
    FillArea( \FillHeure( i )\x , -\FillHeure( i )\y , \Couleur_H )
   Next
  EndIf
  
  ; Dessinne l'axe du cadran
  FrontColor( \CouleurRepereCadran )
  DrawingMode( #PB_2DDrawing_Default  )
  Circle ( 0, 0, 2 )
  
  ;StopDrawing()
  
 EndWith
EndProcedure

; Procedures Publiques
Procedure   Obj_Horloge_NewAiguille     ( *This.Obj_Horloge_Typ , Typ.s           )      ; Mise a zéro, nouvelles aiguilles
 With *This
  Select UCase( Typ ) 
   Case "H"
    \NbPointAigui_H    = -1
    \NbPointFill_H    = -1
    \Remplissage_H    = #False
   ;CaseEnd
   ;Case "M" 
   ; \NbPointAigui_M    = -1
   ; \NbPointFill_M    = -1
   ; \Remplissage_M    = #False
   ;;CaseEnd
   Case "S"
    \NbPointAigui_S    = -1
    \NbPointFill_S    = -1
    \Remplissage_S    = #False
   ;CaseEnd
   Default
    \NbPointAigui_H    = -1
    ;\NbPointAigui_M    = -1
    \NbPointAigui_S    = -1
    
    \NbPointFill_H    = -1
    ;\NbPointFill_M    = -1
    \NbPointFill_S    = -1
    
    \Remplissage_H    = #False
    ;\Remplissage_M    = #False
    \Remplissage_S    = #False
   ;DefaultEnd
  EndSelect
 EndWith
EndProcedure
Procedure   Obj_Horloge_AddPointAiguille  ( *This.Obj_Horloge_Typ , Typ.s , Dx.w  , Dy.w   )      ; Ajoute une coordonnée au dessin des aiguilles , Coordonnéesen %
 Protected .w X  , Y
 Protected .w Dmin , Dmax , DifX , DifY
 With *This
  X  = \Rayon * Dx / 100
  Y  = \Rayon * Dy / 100
  Select UCase( Typ )
   Case "H"
    \NbPointAigui_H + 1
    If \NbPointAigui_H > \NbPointAigui
     \NbPointAigui_H - 1
     MessageRequester( "Limite atteinte" , Str( \NbPointAigui + 1 ) + " Points MAXI" , #PB_MessageRequester_Ok )
     ProcedureReturn -1
    Else
     \AiguilleHeure  ( \NbPointAigui_H )\X   = X
     \AiguilleHeure  ( \NbPointAigui_H )\Y   = Y
     \AiguilleHeure  ( \NbPointAigui_H )\Ray  = GetModule  ( X , Y )
     \AiguilleHeure  ( \NbPointAigui_H )\Arg  = GetAngleRad ( X , Y )
    EndIf
   ;CaseEnd
   ;Case "M"
   ; \NbPointAigui_M + 1
   ; If \NbPointAigui_M > \NbPointAigui
   ;  \NbPointAigui_M - 1
   ;  MessageRequester( "Limite atteinte" , Str( \NbPointAigui + 1 ) + " Points MAXI" , #PB_MessageRequester_Ok )
   ;  ProcedureReturn -1
   ; Else
   ;  \AiguilleMinute  ( \NbPointAigui_M )\X   = X
   ;  \AiguilleMinute  ( \NbPointAigui_M )\Y   = Y
   ;  \AiguilleMinute  ( \NbPointAigui_M )\Ray  = GetModule  ( X , Y )
   ;  \AiguilleMinute  ( \NbPointAigui_M )\Arg  = GetAngleRad ( X , Y )
   ; EndIf
   ;;CaseEnd
   Case "S"
    \NbPointAigui_S + 1
    If \NbPointAigui_S > \NbPointAigui
     \NbPointAigui_S - 1
     MessageRequester( "Limite atteinte" , Str( \NbPointAigui + 1 ) + " Points MAXI" , #PB_MessageRequester_Ok )
    Else
     \AiguilleSeconde ( \NbPointAigui_S )\X   = X
     \AiguilleSeconde ( \NbPointAigui_S )\Y   = Y
     \AiguilleSeconde ( \NbPointAigui_S )\Ray  = GetModule  ( X , Y )
     \AiguilleSeconde ( \NbPointAigui_S )\Arg  = GetAngleRad ( X , Y )
    EndIf
   ;CaseEnd
  EndSelect
 EndWith
EndProcedure
Procedure   Obj_Horloge_AddPointFill    ( *This.Obj_Horloge_Typ , Typ.s , Dx.w  , Dy.w  )      ; Ajoute une coordonnée pour le remplissage   , Coordonnéesen %
 Protected .w X  , Y
 With *This
  X  = \Rayon * Dx / 100
  Y  = \Rayon * Dy / 100
  Select UCase( Typ ) 
   Case "H"
    \NbPointFill_H + 1
    If \NbPointFill_H > \NbPointAigui
     \NbPointFill_H - 1
     MessageRequester( "Limite atteinte" , Str( \NbPointAigui + 1 ) + " Points MAXI" , #PB_MessageRequester_Ok )
     ProcedureReturn -1
    Else
     \FillHeure   ( \NbPointFill_H )\X   = X
     \FillHeure   ( \NbPointFill_H )\Y   = Y
     \FillHeure   ( \NbPointFill_H )\Ray  = GetModule  ( X , Y )
     \FillHeure   ( \NbPointFill_H )\Arg  = GetAngleRad ( X , Y )
     \Remplissage_H = #True
    EndIf
   ;CaseEnd
   ;Case "M"
   ; \NbPointFill_M + 1
   ; If \NbPointFill_M > \NbPointAigui
   ;  \NbPointFill_M - 1
   ;  MessageRequester( "Limite atteinte" , Str( \NbPointAigui + 1 ) + " Points MAXI" , #PB_MessageRequester_Ok )
   ;  ProcedureReturn -1
   ; Else
   ;  \FillMinute   ( \NbPointFill_M )\X   = X
   ;  \FillMinute   ( \NbPointFill_M )\Y   = Y
   ;  \FillMinute   ( \NbPointFill_M )\Ray  = GetModule  ( X , Y )
   ;  \FillMinute   ( \NbPointFill_M )\Arg  = GetAngleRad ( X , Y )
   ;  \Remplissage_M = #True
   ;  
   ; EndIf
   ;;CaseEnd
   Case "S"
    \NbPointFill_S + 1
    If \NbPointFill_S > \NbPointAigui
     \NbPointFill_S - 1
     MessageRequester( "Limite atteinte" , Str( \NbPointAigui + 1 ) + " Points MAXI" , #PB_MessageRequester_Ok )
     ProcedureReturn -1
    Else
     \FillSeconde  ( \NbPointFill_S )\X   = X
     \FillSeconde  ( \NbPointFill_S )\Y   = Y
     \FillSeconde  ( \NbPointFill_S )\Ray  = GetModule  ( X , Y )
     \FillSeconde  ( \NbPointFill_S )\Arg  = GetAngleRad ( X , Y )
     \Remplissage_S = #True
    EndIf
   ;CaseEnd
  EndSelect
 EndWith
EndProcedure
Procedure   Obj_Horloge_SetColor      ( *This.Obj_Horloge_Typ , Typ.s , Coul.i       )      ; Couleurs des aiguilles
 With *This
  Select UCase( Typ ) 
   Case "H"
    \Couleur_H = Coul
   ;CaseEnd
   ;Case "M"
   ; \Couleur_M = Coul
   ;;CaseEnd
   Case "S"
    \Couleur_S = Coul
   ;CaseEnd
  EndSelect
 EndWith
 
EndProcedure
Procedure   Obj_Horloge_SetTime       ( *This.Obj_Horloge_Typ , Time.q          )      ; mise a jour de l'horloge
 Protected .u Heures    , Minutes    , Seconds
 Protected .f AngleHeures , AngleMinutes , AngleSecondes
 
 Heures    = Hour  ( Time ) 
 Minutes    = Minute ( Time ) 
 Seconds    = Second ( Time )
 
 With *This
  ; Si changement de second
  If Seconds <> \OldSec
   ; Calcule l'angle de chacunes des aiguilles
   AngleHeures     = -\Sens * \RadParSeconde_H * ( 3600 * Heures  + 60 * Minutes + Seconds )
   ;AngleMinutes    = -\Sens * \RadParSeconde_M * (                  60 * Minutes + Seconds )
   AngleSecondes    = -\Sens * \RadParSeconde  * (                 Seconds ) ; \RadParSeconde_S * Seconds 
   ;Obj_Horloge_CalcPtsAiguille ( *This , AngleHeures , AngleMinutes , AngleSecondes )
   Obj_Horloge_CalcPtsAiguille ( *This , AngleHeures , 0 , AngleSecondes )
   
   
   Select \GadgetTyp
    Case #PL_GadgetType_Image
     FreeImage( \CadranHorloge )
     \CadranHorloge = CopyImage  ( \CadranFond , #PB_Any )
     StartDrawing ( ImageOutput( \CadranHorloge ) )
      Obj_Horloge_DessineAiguille ( *This )
     StopDrawing()
     ; Rafraichi l'affichage en Plaqant le fichier image dans l'objet ImageGadget
     SetGadgetState ( \GadgetImage , ImageID( \CadranHorloge ) )
    ;CaseEnd
    Case #PL_GadgetType_Canvas
     StartDrawing ( CanvasOutput( \GadgetImage ) )
      DrawImage( ImageID( \CadranFond ) , 0 , 0 )
      Obj_Horloge_DessineAiguille ( *This )
     StopDrawing()
    ;CaseEnd
    Case #PL_GadgetType_Screen
     StartDrawing ( ScreenOutput( ) )
      DrawImage( ImageID( \CadranFond ) , 0 , 0 )
      Obj_Horloge_DessineAiguille ( *This )
     StopDrawing()
     FlipBuffers()
    ;CaseEnd
   EndSelect
   
   \OldSec = Seconds
  EndIf
 EndWith
EndProcedure
Procedure   Obj_Horloge_SetTexte      ( *This.Obj_Horloge_Typ , Nom.s , Dx.w , Dy.w  , Txt.s  )  ; Affiche un texte sur l'horloge    , Coordonnéesen % 
 With *This
  AddMapElement( \MapTexte( ) , Nom , #PB_Map_ElementCheck )
  \MapTexte( )\x    = Dx
  \MapTexte( )\y    = Dy
  \MapTexte( )\Txt   = Txt
 EndWith
EndProcedure
Procedure   Obj_Horloge_SetFont       ( *This.Obj_Horloge_Typ , Txt.s , Dh.a  , Styl.i )      ; Police du texte et hauteur du texte en %
 With *This
  \PoliceTxt = Txt
  \TexteH   = \Rayon * Dh / 100
  If \Police : FreeFont( 0 ) : EndIf
  \Police   = LoadFont( 0 , \PoliceTxt , \TexteH , Styl )
 EndWith
EndProcedure
Procedure   Obj_Horloge_SetSens       ( *This.Obj_Horloge_Typ , SensRot.b         )      ; Sens de rotation des aiguilles +1 -1
 With *This
  \Sens         = Sign( SensRot )
 EndWith
EndProcedure
Procedure   Obj_Horloge_Free        ( *This.Obj_Horloge_Typ               )      ; Libère les resources
 With *This
  If \GadgetTyp = #PL_GadgetType_Screen : CloseScreen ( ) : EndIf
  FreeMemory ( *This )
 EndWith
EndProcedure

; Procedures d'initialisation de l'objet
Procedure .i Obj_Horloge_Init        ( GadImg.i , ColFond.i , FullWin.b=0        )      ; Initialisation de l'horloge
 Protected *Object.Obj_Horloge_Typ
 
 *Object = AllocateMemory( SizeOf( Obj_Horloge_Typ ) )
 If *Object
  With *Object
   \DSVT         = ?Obj_Horloge_Class
   
   If IsGadget( GadImg )
    If GadgetType( GadImg ) = #PB_GadgetType_Canvas
     \DimX         = GadgetWidth  ( GadImg )
     \DimY         = GadgetHeight ( GadImg )
     \GadgetTyp      = #PL_GadgetType_Canvas
     
    ElseIf GadgetType( GadImg ) = #PB_GadgetType_Image
     \DimX         = GadgetWidth  ( GadImg )
     \DimY         = GadgetHeight ( GadImg )
     \GadgetTyp      = #PL_GadgetType_Image
    EndIf
    
   ElseIf IsWindow( GadImg )
    If FullWin
    \DimX         = WindowWidth   ( GadImg , #PB_Window_FrameCoordinate ) - 2
    \DimY         = WindowHeight  ( GadImg , #PB_Window_FrameCoordinate ) - 2
    Else
    \DimX         = WindowWidth   ( GadImg ) 
    \DimY         = WindowHeight  ( GadImg ) - MenuHeight ( )
   EndIf
   
    \GadgetTyp      = #PL_GadgetType_Screen
    InitSprite  ( )
    OpenWindowedScreen ( WindowID( GadImg ) ,  1 , 1 , \DimX , \DimY )
    
   Else
    MessageRequester( "Erreur." , "Un ImageGadget, CanvasGadget ou une fenêtre est attendu." , #PB_MessageRequester_Error  | #PB_MessageRequester_Ok )
    End
    
   EndIf
   
   
   If \DimX < \DimY : \Diametre = \DimX
   Else       : \Diametre = \DimY
   EndIf
   \Rayon        = Int( \Diametre / 2.0 ) - 1
   \RadParSeconde_H   = #PI / 43200.0  ;( 24 * 60 * 60 ) / 2
   ;\RadParSeconde_M   = #PI /  1800.0  ;(     60 * 60 ) / 2
   \RadParSeconde_S   = #PI /    72.0  ;(   24 * 6  ) / 2
   \RadParSeconde    = #PI /    30.0  ;(      60 ) / 2
   
   
   \Sens         = 1
   \Couleur_H      = $00ff00    ; ( B, V, R ) Vert
   ;\Couleur_M      = $ff0000    ; ( B, V, R ) Bleu
   \Couleur_S      = $0000ff    ; ( B, V, R ) Rouge
   \CouleurFond     = ColFond
   \CouleurRepereCadran = \CouleurFond ! $FFFFFF
   \NbPointAigui     = 31     ; ( 32 points maxi de 0 a 31 )
   \NbPointAigui_H    = -1
   ;\NbPointAigui_M    = -1
   \NbPointAigui_S    = -1
   
   \NbPointFill_H    = -1
   ;\NbPointFill_M    = -1
   \NbPointFill_S    = -1
   
   
   \GadgetImage     = GadImg
   \CadranFond      = CreateImage ( #PB_Any   , \DimX , \DimY , 32 , \CouleurFond )
   \CadranHorloge    = CopyImage  ( \CadranFond , #PB_Any )
   \RayonMini      = 0.95 * \Rayon
   \RayonMaxi      = 0.99 * \Rayon
   \RayonUnit      = 0.05 * \Rayon
   
   \RayonMini_S     = 0.80 * \Rayon
   \RayonMaxi_S     = 0.85 * \Rayon
   \RayonUnit_S     = 0.05 * \Rayon
   \OldSec        = 0
   
   \TexteH        = \Rayon * 10 / 100
   \PoliceTxt      = "Arial"
   \Police        = LoadFont( 0 , \PoliceTxt , \TexteH , 0 )
   
   \Remplissage_H    = #False
   ;\Remplissage_M    = #False
   \Remplissage_S    = #False
   
   NewMap \MapTexte   .Texte   (  ) 
   
   Dim \AiguilleHeure  .Coordonnee( \NbPointAigui )
   ;Dim \AiguilleMinute  .Coordonnee( \NbPointAigui )
   Dim \AiguilleSeconde .Coordonnee( \NbPointAigui )
   Dim \FillHeure    .Coordonnee( \NbPointAigui )
   ;Dim \FillMinute    .Coordonnee( \NbPointAigui )
   Dim \FillSeconde   .Coordonnee( \NbPointAigui )
   
   ; Initialise des aiguilles par defaut
   ; Aiguille des heures
   Obj_Horloge_AddPointAiguille( *Object , "H" ,   0 ,  95 ) ; 0
   Obj_Horloge_AddPointAiguille( *Object , "H" ,   0 , -10 ) ; 1
   
   ; Aiguille des secondes
   Obj_Horloge_AddPointAiguille( *Object , "S" ,   0 ,  80 ) ; 0
   Obj_Horloge_AddPointAiguille( *Object , "S" ,   0 , -30 ) ; 1
   
   
   
   ; Initialise le cadran
   Protected .w X1 , Y1 , X2 , Y2
   Protected .f ValCos , ValSin
   Protected .i i
   Protected .s Txt
   
   StartDrawing ( ImageOutput( \CadranFond ) )  ; Demarre la procedure de tracé dans le fichier image
    SetOrigin   ( \DimX / 2 , \DimY / 2 )    ; Place l'origine du tracé
    
    ; Dessine les repère des heures sur le cadran 24h
    FrontColor( \CouleurRepereCadran )
    For i = 0 To 144 ; ( 24 x 6 )
     ValCos = Cos( i * \RadParSeconde_S )
     ValSin = Sin( i * \RadParSeconde_S )
     ; Les repaires 10 minutes
     X1   = \RayonMini
     Y1   = \RayonMini
     ; Les repaires  1 heure
     If i %  6 = 0 : X1 - \RayonUnit : Y1 - \RayonUnit : EndIf
     ; Les repaires 3 heures
     If i % 18 = 0 : X1 - \RayonUnit : Y1 - \RayonUnit : EndIf
     ; Calcule les coordonnées du point 1
     X1   = X1 * ValCos
     Y1   = Y1 * ValSin
     ; Calcule les coordonnées du point 2
     X2   = \RayonMaxi * ValCos
     Y2   = \RayonMaxi * ValSin
     ; Trace les repaires sur le cadran
     LineXY( X1 , -Y1 , X2 , -Y2 )
    Next
    
    ; Dessine les repère des secondes sur le cadran
    FrontColor( RGB( Red( \CouleurRepereCadran ) / 2 , Green( \CouleurRepereCadran ) / 2 , Blue( \CouleurRepereCadran ) / 2 ) )
    For i = 0 To 59 
     ValCos = Cos( i * \RadParSeconde )
     ValSin = Sin( i * \RadParSeconde )
     ; Les repaires 1 seconde
     X1   = \RayonMini_S
     Y1   = \RayonMini_S
     ; Les repaires  5 secondes
     If i %  5 = 0 : X1 - \RayonUnit_S : Y1 - \RayonUnit_S : EndIf
     ; Les repaires 15 secondes
     If i % 15 = 0 : X1 - \RayonUnit_S : Y1 - \RayonUnit_S : EndIf
     ; Calcule les coordonnées du point 1
     X1   = X1 * ValCos
     Y1   = Y1 * ValSin
     ; Calcule les coordonnées du point 2
     X2   = \RayonMaxi_S * ValCos
     Y2   = \RayonMaxi_S * ValSin
     ; Trace les repaires sur le cadran
     LineXY( X1 , -Y1 , X2 , -Y2 )
    Next
    
    ; Affichage textes des heures
    FrontColor  ( \CouleurRepereCadran     )
    BackColor   ( \CouleurFond )
    DrawingFont  ( \Police )
    X1   = 0.70 * \Rayon
    For i = 0 To 144 Step 18  ; ( 24 x 6 )
     ValCos = Cos( i * \RadParSeconde_S - (#PI / 2 ) )
     ValSin = Sin( i * \RadParSeconde_S - (#PI / 2 ) )
     ; Les repaires 3 heures
     If i % 18 = 0
      Txt = Str( i / 6 )
      ; Calcule les coordonnées du point 1
      X2   = X1 * ValCos
      Y2   = X1 * ValSin
      ; Calcule les coordonnées du point 2
      ; Trace les repaires sur le cadran
      X2 = X2 - TextWidth ( Txt ) / 2 
      Y2 = Y2 - TextHeight ( Txt ) / 2 
      DrawText( X2 , Y2 , Txt )
      
     EndIf
    Next
    
    ; Trace L'axe des aiguilles sur le cadran
    Circle ( 0, 0, 2 )
   StopDrawing( )
   
  EndWith
 EndIf
 ProcedureReturn *object
EndProcedure

DataSection
 Obj_Horloge_Class:
 Data.i @Obj_Horloge_NewAiguille     ( )
 Data.i @Obj_Horloge_AddPointAiguille  ( )
 Data.i @Obj_Horloge_AddPointFill    ( )
 Data.i @Obj_Horloge_SetColor      ( )
 Data.i @Obj_Horloge_SetTime       ( )
 Data.i @Obj_Horloge_SetTexte      ( )
 Data.i @Obj_Horloge_SetFont       ( )
 Data.i @Obj_Horloge_SetSens       ( )
 Data.i @Obj_Horloge_Free        ( )
EndDataSection

; ; *******************
; ; *** Utilisation ***
; ; *******************
; ; 
; ; MonHorloge .NewObj_Horloge = Obj_Horloge_Init ( GadImg.i , ColFond.i , FullWin.b=0 ) ; Initialisation de l'horloge
; ; MonHorloge\NewAiguille    ( Typ.s           )               ; Mise a zéro, nouvelles aiguilles
; ; MonHorloge\AddPointAiguille  ( Typ.s , Dx.w , Dy.w   )               ; Ajoute une coordonnée au dessin des aiguilles   , Coordonnéesen %  ; 32 points maxi
; ; MonHorloge\AddPointFill    ( Typ.s , Dx.w , Dy.w    )               ; Ajoute une coordonnée pour le remplissage     , Coordonnéesen %
; ; MonHorloge\SetColor      ( Typ.s , Coul.i      )               ; Couleurs des aiguilles
; ; MonHorloge\SetTime      ( Time.q          )               ; Mise a jour de l'horloge
; ; MonHorloge\SetTexte      ( Dx.w , Dy.w , Txt.s   )               ; Affiche un texte sur l'horloge centée sur le pont , Coordonnées en %
; ; MonHorloge\SetFont      ( Txt.s , Dh.a=10 , Styl.i )               ; Police du texte et hauteur du texte en %
; ; MonHorloge\SetSens      ( SensRot.b         )               ; Sens de rotation des aiguilles +1 -1
; ; MonHorloge\Free        (              )               ; Libère les resources
; ;
; ;; Exemple :
; ;; Init Affichage Horloge Analogique
; Titre$          = "Horloge 24"
; Option          = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_BorderLess
; Win_0           = OpenWindow(#PB_Any, #PB_Ignore , #PB_Ignore , 800 , 600, Titre$ , Option )
; WindowBounds  ( Win_0 , 800 , 600 , #PB_Ignore , #PB_Ignore ) 
; ;ImageHorlogeAnalogique  = ImageGadget     ( #PB_Any , 0 , 0 , WindowWidth(Win_0) , WindowHeight(Win_0) , 0 )
; ;ImageHorlogeAnalogique  = CanvasGadget    ( #PB_Any , 0 , 0 , WindowWidth(Win_0) , WindowHeight(Win_0)   )
; ImageHorlogeAnalogique  = Win_0
; 
; ObjHorlogeAnalogique.NewObj_Horloge   = Obj_Horloge_Init ( ImageHorlogeAnalogique , #Black )
; 
; Repeat
;  
;  ObjHorlogeAnalogique\SetTime      ( Date( ) ) ; Mise a jour de l'horloge
;  Delay(1)
;  
; Until WindowEvent() = #PB_Event_CloseWindow
; 
;} 


;-ScreenSaver Horloge 24h
;{ Version 20260702
Global .i ColAiguilleH  = #Green
Global .i ColAiguilleS  = #Red
Global .s CheminIni$      = GetHomeDirectory() + "AppData\Local\VirtualStore\Windows\"
Global .s FichierIni     = CheminIni$     + "Horloge.Ini"
Global .s ScreensaverName   = "Horloge 24h"
Global .s Parameter      = ""
Global .s previewWndHandleStr = ""

Global ObjHorlogeAnalogique .NewObj_Horloge

Procedure   SauveParametresIni    ( )
 OpenPreferences( FichierIni )
 PreferenceGroup("Horloge")
 WritePreferenceInteger ( "ColAiguilleH" , ColAiguilleH )
 WritePreferenceInteger ( "ColAiguilleS" , ColAiguilleS )
 ClosePreferences()
EndProcedure
Procedure   ChargeParametresIni    ( )
 If OpenPreferences( FichierIni )
  PreferenceGroup("Horloge")
  ColAiguilleH    = ReadPreferenceInteger ( "ColAiguilleH" , #Green )
  ColAiguilleS    = ReadPreferenceInteger ( "ColAiguilleS" , #Red  )
  ClosePreferences()
 Else
  SauveParametresIni    ( )
 EndIf
 
EndProcedure
Procedure   InitAiguille       ( Typ.a = 1 )
 
 ; ***********************
 ; *    Aiguille N°1     *
 ; *                     *
 ObjHorlogeAnalogique\NewAiguille   ( "" )        ; Remise à 0 de l' aiguilles des Heures
 
 ; Initialise des aiguilles par defaut
 ; Aiguille des heures
 ObjHorlogeAnalogique\AddPointAiguille( "H" ,   0 ,  95 )  ; 0
 ObjHorlogeAnalogique\AddPointAiguille( "H" ,   0 , -10 )  ; 1
 
 ; Aiguille des secondes
 ObjHorlogeAnalogique\AddPointAiguille( "S" ,   0 ,  80 ) ; 0
 ObjHorlogeAnalogique\AddPointAiguille( "S" ,   0 , -30 ) ; 1
EndProcedure
Procedure   ConfigScreen       (  ) 
 ; Configuration de l'économiseur, Initialisation fenetre Parametres
 ;{
 
 Options  = #PB_Window_Tool | #PB_Window_ScreenCentered
 Protected .i FenetreParametre       = OpenWindow( #PB_Any , 0 , 0 , 210 , 340 , "Paramètres" ,  Options )
 yPose  = 10
 Protected .i ImageHorlogeAnalogique    = CanvasGadget   ( #PB_Any , 30 , 10  , 150  , 150         ) : yPose + 170
 Protected .i Text_Heure          = TextGadget    ( #PB_Any ,  20 , yPose ,  90  ,  20   , "Heure"  )
 Protected .i ButtonImage_Couleur_Heure   = ButtonImageGadget ( #PB_Any , 120 , yPose ,  40  ,  20   , 0     ) : yPose + 20
 Protected .i Option_Seconde        = TextGadget    ( #PB_Any ,  20 , yPose ,  90  ,  20   , "Seconde" )
 Protected .i ButtonImage_Couleur_Seconde  = ButtonImageGadget ( #PB_Any , 120 , yPose ,  40  ,  20   , 0     ) : yPose + 30
 Protected .i ParamButtonValideParametres  = ButtonGadget   ( #PB_Any , 20 , yPose ,  70  ,  30   , "Valide" )
 Protected .i ParamButtonAnnuleParametres  = ButtonGadget   ( #PB_Any , 120 , yPose ,  70  ,  30   , "Annule" ) : yPose + 40
 ResizeWindow  ( FenetreParametre , #PB_Ignore , #PB_Ignore , #PB_Ignore , yPose )
 ; Initialisation des boutons Image
 Protected .i Image_Couleur_Heure      = CreateImage    ( #PB_Any , 40 , 20 , 32 )
 Protected .i Image_Couleur_Seconde     = CreateImage    ( #PB_Any , 40 , 20 , 32 )
 StartDrawing( ImageOutput( Image_Couleur_Heure ) )
  Box( 0 , 0 , 40 , 20 , ColAiguilleH )
 StopDrawing()
 SetGadgetAttribute( ButtonImage_Couleur_Heure , #PB_Button_Image , ImageID( Image_Couleur_Heure ) )
 
 StartDrawing( ImageOutput( Image_Couleur_Seconde ) )
  Box( 0 , 0 , 40 , 20 , ColAiguilleS )
 StopDrawing()
 SetGadgetAttribute( ButtonImage_Couleur_Seconde , #PB_Button_Image , ImageID( Image_Couleur_Seconde ) )
 
 ;}
 
 ObjHorlogeAnalogique = Obj_Horloge_Init ( ImageHorlogeAnalogique , #Black )
 ; Initialise l'horloge
 InitAiguille       ( TypeAiguille )
 ObjHorlogeAnalogique\SetColor ( "H" , ColAiguilleH )
 ObjHorlogeAnalogique\SetColor ( "S" , ColAiguilleS )
 AddWindowTimer  ( FenetreParametre , 1 , 100 )
 
 Protected .a Fini = #False
 Repeat
  Event = WindowEvent( )
  If Event 
   Select EventWindow()
    Case FenetreParametre
     Select Event
      Case #PB_Event_Timer
       If EventTimer( ) = 1
        ObjHorlogeAnalogique\SetTime  ( Date  ( ) )
       EndIf   
      ;CaseEnd
      Case #PB_Event_Gadget
       Select EventGadget()
        Case ParamButtonValideParametres
         SauveParametresIni( )
         Fini = #True
        ;CaseEnd
        Case ParamButtonAnnuleParametres
         Fini = #True
        ;CaseEnd
        Case ButtonImage_Couleur_Heure
         Couleur = ColorRequester()
         If Couleur > -1
          ColAiguilleH = Couleur
          StartDrawing( ImageOutput( Image_Couleur_Heure ) )
           Box( 0 , 0 , 40 , 20 , ColAiguilleH )
          StopDrawing()
          SetGadgetAttribute( ButtonImage_Couleur_Heure , #PB_Button_Image , ImageID( Image_Couleur_Heure ) )
          ObjHorlogeAnalogique\SetColor( "H" , ColAiguilleH )
         EndIf
        ;CaseEnd
        Case ButtonImage_Couleur_Seconde
         Couleur = ColorRequester()
         If Couleur > -1
          ColAiguilleS = Couleur
          StartDrawing( ImageOutput( Image_Couleur_Seconde ) )
           Box( 0 , 0 , 40 , 20 , ColAiguilleS )
          StopDrawing()
          SetGadgetAttribute( ButtonImage_Couleur_Seconde , #PB_Button_Image , ImageID( Image_Couleur_Seconde ) )
          ObjHorlogeAnalogique\SetColor( "S" , ColAiguilleS )
         EndIf
        ;CaseEnd
       EndSelect
      ;CaseEnd
     EndSelect 
    ;CaseEnd
   EndSelect
  Else
   Delay( 10 )
  EndIf
 Until Fini
 CloseWindow( FenetreParametre )
EndProcedure 

;***********************
;* Programme principal *
;***********************
; Autoriser une seule instance de ce programme
ScreenSaver::Start(ScreensaverName)
ChargeParametresIni()

Parameter  = ScreenSaver::GetParameter()
Select UCase( Parameter )
 Case "C" ;"C" => écran de configuration.
  ConfigScreen( )
  End
 ;CaseEnd
 Case "P" ; Aperçu. Ce paramètre est suivi d'un autre, le handle de la fenêtre d'aperçu : '-p -123456' ou  '/p /12345'
  Win_0  = ScreenSaver::GetWinPreview(  ) ; previewWndHandleStr
 ;CaseEnd
 Case "S" , "" ; Mode économiseur d'écran
  Win_0  = ScreenSaver::GetWinSaver()
 ;CaseEnd
 Default
  End
 ;DefaultEnd
EndSelect

ObjHorlogeAnalogique   = Obj_Horloge_Init ( Win_0 , #Black , 1 )
; Initialise l'horloge
InitAiguille       ( TypeAiguille )
ObjHorlogeAnalogique\SetColor ( "H" , ColAiguilleH )
ObjHorlogeAnalogique\SetColor ( "S" , ColAiguilleS )
AddWindowTimer  ( Win_0 , 1 , 100 )

Repeat
 Evenement = WaitWindowEvent( )
 
 Select Evenement
  Case #PB_Event_Timer
   If EventTimer( ) = 1
    ObjHorlogeAnalogique\SetTime  ( Date  ( ) )
   EndIf   
  ;CaseEnd
 EndSelect
 
 If ScreenSaver::IsScreenSaverMode() And ScreenSaver::CheckStatus()
  ScreenSaver::Stop()
  Break
 EndIf
 
ForEver 

ObjHorlogeAnalogique\Free( )

;}

Avatar de l’utilisateur
SPH
Messages : 5105
Inscription : mer. 09/nov./2005 9:53

Re: Ecran de veille : Horloge analogique 24h.

Message par SPH »

J'en avais fait une qui contenait l'esprit "SCR" car elle bouge.
En effet, un screensaver ne doit pas "marquer" un pixel sur les vieux moniteurs :

Code : Tout sélectionner

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  Les horloges de SPH  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Code : SPH(2022) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;é

InitSprite() 
InitMouse() 
InitKeyboard() 

;SetPriorityClass_ ( GetCurrentProcess_ (), #IDLE_PRIORITY_CLASS ) 

ExamineDesktops()
dw.w=DesktopWidth(0) 
dh.w=DesktopHeight(0)
do.b=DesktopDepth(0)

OpenScreen(dw,dh,do,"Les horloges de SPH") 


xx=dw/2
yy=dh/2
pis.f=ATan(1)*12.1585
pim.f=ATan(1)*12.1585
pih.f=ATan(1)*2.4317
echp=yy/1.4
;echh=yy/2.4
echm=yy/1.5
col=RGB(33,33,33)
ii.f=Random(20)/100
uu.f=Random(20)/100
ii2.f=Random(20)/100
uu2.f=Random(20)/100

;;;;;;;;;;;
sphii.f=0
sphuu.f=0
sphii2.f=0
sphuu2.f=0
sphiii.f=Random(1000)/100000
sphuuu.f=Random(1000)/100000
sphiii2.f=Random(1000)/100000
sphuuu2.f=Random(1000)/100000
rayonx=dw/5
rayony=dh/6
ShowCursor_(0)
;;;;;;;;;;;
;;;;;;;;;;;

MouseLocate(xx,yy)

Repeat ; Boucle principale

xxx=Cos(ii)*45+Sin(ii2)*40
yyy=Sin(uu)*45-Cos(uu2)*40
decx.f=Cos(ii)/18+Sin(uu2)/15

ExamineMouse()
x2mouse=MouseX()
y2mouse=MouseY()

xmouse=Cos(sphii)*rayonx+Sin(sphii2)*rayonx
ymouse=Sin(sphuu)*rayony+Cos(sphuu2)*rayony

xx2021=xmouse+x2mouse
yy2021=ymouse+y2mouse



If MouseButton(#PB_MouseButton_Left)<>0
s+1:If s>=60:s-60:m+1:EndIf:If m=60:m=0:h+1:EndIf:If h=12:h=0:EndIf
Else
h=Hour(Date()):m=Minute(Date()):s=Second(Date())
EndIf

If MouseButton(#PB_MouseButton_Right)<>0
sphiii.f=Random(1000)/100000
sphuuu.f=Random(1000)/100000
sphiii2.f=Random(1000)/100000
sphuuu2.f=Random(1000)/100000
EndIf


;*****
ClearScreen(0)
StartDrawing(ScreenOutput()) 
;;;;;;;;;;;
ss.f=decx+s/pis
mm.f=decx+(m+s/60)/pim
hh.f=decx+(h+m/60)/pih
For i=0 To 11
For u=1 To 5
If i=0 Or i=3 Or i=6 Or i=9
co=RGB(255,255,255)
Else
co=RGB(80,80,80)
EndIf

  sphx=xx2021+Sin(decx+i/pih)*(echp+xxx)+Random(6)-3 ;;;;;;;;;;;;xx
  sphy=yy2021-Cos(decx+i/pih)*(echp+yyy)+Random(6)-3 ;;;;;;;;;;;;yy
  
  If sphx<0
    co=RGB(00,80,00)
  sphx=(sphx*-1)/2
  EndIf
  If sphx>=dw
    co=RGB(00,80,00)
    sphx=dw-1-Abs(dw-sphx)/2
  EndIf
  
  If sphy<0
    co=RGB(00,80,00)
  sphy=(sphy*-1)/2
  EndIf
  If sphy>=dh
    co=RGB(00,80,00)
  sphy=dh-1-Abs(dh-sphy)/2
  EndIf
  
  Plot(sphx,sphy,co)
Next
Next


x1=Sin(mm)*(echm+xxx)
y1=-Cos(mm)*(echm+yyy)
;Line(xx,yy,x1,y1,RGB(200,200,0))
dist=Sqr(x1*x1+y1*y1)
xx1.f=x1/dist
yy1.f=y1/dist
xx2.f=xx2021;;;;;;;xx
yy2.f=yy2021;;;;;;;yy
u=0
;r=255;Random(255)
For i=0 To dist/3
  co=RGB(255,255,00)
  sphx=xx2-u/32+Random(u/16)
  sphy=yy2-u/32+Random(u/16)
  If sphx<0
    co=RGB(00,80,00)
  sphx=(sphx*-1)/2
  EndIf
  If sphx>=dw
    co=RGB(00,80,00)
    sphx=dw-1-Abs(dw-sphx)/2
  EndIf
  
  If sphy<0
    co=RGB(00,80,00)
  sphy=(sphy*-1)/2
  EndIf
  If sphy>=dh
    co=RGB(00,80,00)
    sphy=dh-1-Abs(dh-sphy)/2
  EndIf
  
Plot(sphx,sphy,co)
xx2+xx1
yy2+yy1
u+2
Next
;r=255;Random(255)
For i=0 To dist/2
  co=RGB(255,255,00)
  u-1
  sphx=xx2-u/32+Random(u/16)
  sphy=yy2-u/32+Random(u/16)
  If sphx<0
    co=RGB(00,80,00)
  sphx=(sphx*-1)/2
  EndIf
  If sphx>=dw
    co=RGB(00,80,00)
    sphx=dw-1-Abs(dw-sphx)/2
  EndIf
  
  If sphy<0
    co=RGB(00,80,00)
  sphy=(sphy*-1)/2
  EndIf
  If sphy>=dh
    co=RGB(00,80,00)
    sphy=dh-1-Abs(dh-sphy)/2
  EndIf
  
Plot(sphx,sphy,co)
xx2+xx1
yy2+yy1
Next


x1=Sin(hh)*(echm+xxx)
y1=-Cos(hh)*(echm+yyy)
dist=Sqr(x1*x1+y1*y1)
xx1.f=x1/dist
yy1.f=y1/dist
xx2.f=xx2021;;;;;;;xx
yy2.f=yy2021;;;;;;;yy
u=0
;r=255;Random(255)
For i=0 To dist/8
  co=RGB(255,20,86)
  sphx=xx2-u/8+Random(u/4)
  sphy=yy2-u/8+Random(u/4)
  If sphx<0
    co=RGB(00,80,00)
  sphx=(sphx*-1)/2
  EndIf
  If sphx>=dw
    co=RGB(00,80,00)
    sphx=dw-1-Abs(dw-sphx)/2
  EndIf
  
  If sphy<0
    co=RGB(00,80,00)
  sphy=(sphy*-1)/2
  EndIf
  If sphy>=dh
    co=RGB(00,80,00)
    sphy=dh-1-Abs(dh-sphy)/2
  EndIf
  
Plot(sphx,sphy,co)
xx2+xx1
yy2+yy1
u+2
Next
r=255;Random(255)
For i=0 To dist/4
  u-1
    co=RGB(255,20,86)
    sphx=xx2-u/8+Random(u/4)
  sphy=yy2-u/8+Random(u/4)
  If sphx<0
    co=RGB(00,80,00)
  sphx=(sphx*-1)/2
  EndIf
  If sphx>=dw
    co=RGB(00,80,00)
    sphx=dw-1-Abs(dw-sphx)/2
  EndIf
  
  If sphy<0
    co=RGB(00,80,00)
  sphy=(sphy*-1)/2
  EndIf
  If sphy>=dh
    co=RGB(00,80,00)
    sphy=dh-1-Abs(dh-sphy)/2
  EndIf
  
Plot(sphx,sphy,co)
xx2+xx1
yy2+yy1
Next

x1=Sin(ss)*(echm+xxx)
y1=-Cos(ss)*(echm+yyy)
dist=Sqr(x1*x1+y1*y1)
xx1.f=x1/dist
yy1.f=y1/dist
xx2.f=xx2021-2;;;;;;;xx-2
yy2.f=yy2021-2;;;;;;;yy-2
For i=0 To dist
  If Random(2)=1
    co=RGB(86,20,255)
    sphx=xx2+Random(4)
  sphy=yy2+Random(4)
  If sphx<0
    co=RGB(00,80,00)
  sphx=(sphx*-1)/2
  EndIf
  If sphx>=dw
    co=RGB(00,80,00)
    sphx=dw-1-Abs(dw-sphx)/2
  EndIf
  
  If sphy<0
    co=RGB(00,80,00)
  sphy=(sphy*-1)/2
  EndIf
  If sphy>=dh
    co=RGB(00,80,00)
    sphy=dh-1-Abs(dh-sphy)/2
  EndIf
  
Plot(sphx,sphy,co)
EndIf
xx2+xx1
yy2+yy1
Next

ii+0.007
uu+0.0059
ii2+0.0043
uu2+0.0031

sphii.f+sphiii.f
sphuu.f+sphuuu.f
sphii2.f+sphiii2.f
sphuu2.f+sphuuu2.f

;;;;;;;;;;;
StopDrawing() 
;*****

FlipBuffers() 

Delay(1)

ExamineKeyboard() 
Until KeyboardPushed(#PB_Key_All)
ShowCursor_(1)
End 


!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Avatar de l’utilisateur
plabouro472
Messages : 53
Inscription : sam. 23/juil./2022 10:17

Re: Ecran de veille : Horloge analogique 24h.

Message par plabouro472 »

SPH a écrit : ven. 03/juil./2026 17:41 J'en avais fait une qui contenait l'esprit "SCR" car elle bouge.
En effet, un screensaver ne doit pas "marquer" un pixel sur les vieux moniteurs :

Une horloge qui scintille, c'est plutôt sympa, bravo.
Avatar de l’utilisateur
SPH
Messages : 5105
Inscription : mer. 09/nov./2005 9:53

Re: Ecran de veille : Horloge analogique 24h.

Message par SPH »

Merci

Ton horloge est très sympa aussi :wink:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Répondre