Gambas France BETA


Pas de compte ? Incription

Exemple 21 :

Faire une horloge analogique :


Le lien vers un exemple de la forge : Horloge
Une image :



En cliquant droit on fait apparaître un menu contextuel qui permet de sélectionner des images d'horloges différentes,
d'afficher la date, le logo ou les deux et de sortir du programme.
Le clique gauche est conservé pour effectuer les déplacements de l'horloge.

Logique de construction de l'horloge :



Une horloge tourne dans le sens inverse du cercle trigonométrique.
L'origine de l'horloge est à 12 heures.
l'origine du cercle trigonométrique est à 3 heures.
la translation entre les deux est donc de - 90 degrés.

Une heure = 60 minutes = 3 600 secondes.
Un tour c'est 360 degrés réalisé soit en 60 secondes soit en 60 minutes.
soit 360 / 60 = 6.
en milliseconde : 60 x 1 000 = 60 000.
soit pour un tour : 360 / 60 000 = 0,006
ou son inverse : 60 000 / 360 = 166,6666666667.

Donc pour représenter l'angle d'avancé sur l'horloge :
Angle en degrés pour les heures = (heures x 60 + minutes) / 2 - 90°.
Angle en degrés pour les minutes = minutes x 360 / 60 - 90°.
Angle en degrés pour les secondes = secondes x 360 / 60 - 90°.
Angle en degrés pour les millisecondes = (secondes x 360 / 60 + millisecondes x 360 / 60 000) - 90°.

Pour placer les objets comme les aiguilles sur l'horloge, les coordonnées sur le cercle sont :
Les angles étant convertis de degrés en radians
X = rayon (aiguilles) x Cos(Angle).
Y = rayon (aiguilles) x Sin(Angle).

Pour chaque type d'aiguille , pour obtenir la longueur voulue, il suffit d'appliquer un coefficient réducteur.




Le Code :


Le code du formulaire principal :

Les déclarations :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
' Gambas class file

STATIC PUBLIC iDesign AS INTEGER
STATIC PUBLIC iDrap AS INTEGER
STATIC PUBLIC bTrotteuse AS BOOLEAN
STATIC PUBLIC bAuto AS BOOLEAN
STATIC PUBLIC sText1 AS STRING
STATIC PUBLIC sText2 AS STRING

PRIVATE $hPicture AS Picture
PRIVATE $iNbreImage AS INTEGER = 12 '<-------------------------------' nombre d'images enregistrées
PRIVATE $iHandLength AS NEW INTEGER[$iNbreImage + 1]
PRIVATE $cHandColor AS NEW INTEGER[$iNbreImage + 1]
PRIVATE $hConsoleTimer AS Timer
PRIVATE $iCount AS INTEGER

'The drawing of the clock(s) is based on procedures provided by Hans Lehmann and Ingo Beckert.
'For the user rights please refer to: [url=http://gambas-buch.de/dw/doku.php?id=impressum]http://gambas-buch.de/dw/doku.php?id=impressum[/url]:start
'Claus Dietrich

Dimensions des images :
1
2
3
4
5
6
7
8
9
10
PRIVATE SUB dimPicture1()

PictureBox1.X = 0
PictureBox1.Y = 0
PictureBox1.W = 199
PictureBox1.H = 199
PictureBox1.Mode = PictureBox.Contain
PictureBox1.Tooltip = ("Clique droit pour options")

END

Les aiguilles de notre montre :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
PRIVATE SUB paramAiguilles()

DIM i AS INTEGER

'<----------------------------------------------------------------' Base length of the hands
FOR i = 0 TO $iNbreImage '<---------------------------------------' voir la déclaration du nombre d'images
SELECT CASE i '<----------------------------------------------' à corriger si ajout de design
CASE 3
$iHandLength[i] = 70
CASE 8
$iHandLength[i] = 90
CASE ELSE
$iHandLength[i] = 75
END SELECT
NEXT
'<----------------------------------------------------------------' Color of the hands
FOR i = 0 TO $iNbreImage
SELECT CASE i '<----------------------------------------------' à corriger si ajout de design
CASE 0
$cHandColor[i] = Color.DarkGray
CASE 1, 2
$cHandColor[i] = Color.white
CASE 5
$cHandColor[i] = Color.Yellow
CASE 10
$cHandColor[i] = Color.Green
CASE ELSE
$cHandColor[i] = Color.black
END SELECT
NEXT

END

Actions menu contextuel :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
PRIVATE SUB options()' <-------------------------------------------' actions des options du menu contextuel

DIM sLogoText AS STRING '<---------------------------------------' pour incrustation texte voir plus bas
DIM W, H AS FLOAT
DIM texte1 AS STRING = sText1 '<----------------------------------' choisir son texte
DIM texte2 AS STRING = sText2 '<----------------------------------' choisir son texte

w = PictureBox1.W
h = PictureBox1.h

SELECT CASE iDesign '<-------------------------------------------' options de couleur et de taille des fonts pour les design
CASE 10, 11, 12
paint.Brush = paint.Color(&000000)
paint.font = Font["World of Water, 13,bold"]
CASE ELSE
paint.Brush = paint.Color(&C0A74C)
paint.font = Font["World of Water, 12, "]
END SELECT

SELECT CASE iDrap
CASE 0 '<----------------------------------------------------' Option 0: ?riting nada
sLogoText = ""
paint.DrawText(sLogoText, w / 2 - paint.TextSize(sLogoText).w / 2, 134, 10, 10)
CASE 1 '<----------------------------------------------------' Option 1: Writing text
sLogoText = texte1
paint.DrawText(sLogoText, w / 2 - paint.TextSize(sLogoText).w / 2, 120, 10, 10)
sLogoText = texte2
paint.DrawText(sLogoText, w / 2 - paint.TextSize(sLogoText).w / 2, 134, 10, 10)
CASE 2 '<------------------------------------------------------' Option 2: ?riting Date
sLogoText = Format$(Now, "dd. mmm yyyy")
paint.DrawText(sLogoText, w / 2 - paint.TextSize(sLogoText).w / 2, 134, 10, 10)
CASE 3 '<----------------------------------------------------' Option 3: writing logo
Paint.DrawPicture(Picture["icon:/32/gambas"], w / 2.5, h / 1.9, 50, 50)
CASE 4 '<----------------------------------------------------' Option 4 writing logo and date
sLogoText = Format$(Now, "dd. mmm yyyy")
paint.DrawText(sLogoText, w / 2 - paint.TextSize(sLogoText).w / 2, 134, 10, 10)
Paint.DrawPicture(Picture["icon:/32/gambas"], w / 2.3, h / 1.9, 30, 30)
END SELECT

END

Fonction pour dessiner les aiguilles :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
PRIVATE FUNCTION Zeichnen(x AS FLOAT, y AS FLOAT, hColor AS INTEGER, iLW AS INTEGER, W AS FLOAT, H AS FLOAT) AS INTEGER
'<----------------------------------------------------------------' fonction pour dessiner les aiguilles

paint.Brush = paint.Color(hColor)
paint.LineWidth = iLW
paint.LineCap = paint.LineCapRound
paint.MoveTo((W + 1) / 2, (H + 1) / 2)
paint.RelLineTo(x, y)
paint.Stroke

END

PRIVATE SUB PaintClock(temps AS DATE) '<----------------------------' peinture des aiguilles

DIM x, y AS SINGLE
DIM iRadius AS INTEGER
DIM Winkel AS FLOAT
DIM W, H AS FLOAT

DIM m AS FLOAT = 0.67 '0.67 'd'origine 'dimensions aiguilles réduites de ce rapport pour les heures
DIM p AS FLOAT = 6 '6 =360°/60s 'Tic des minutes ou des secondes correspond à l'angle de rotation en degrés
DIM c AS FLOAT = 0.2 '0.2' d'origine 'dimensions aiguilles opposées réduites de ce rapport
DIM pk AS FLOAT = 30 '30=60'/2 'Tic des heures correspond à l'angle de rotation en degrés
DIM rp AS FLOAT = 1 'rapport du timer 'ne sert à rien mais semble rendre l'image plus fluide

w = PictureBox1.W '<----------------------------------------------' Dimensions en rapport de FMain
h = PictureBox1.h '<----------------------------------------------' Dimensions en rapport de FMain

$hPicture = NEW Picture(w, h, TRUE) '<---------------------------' image des aiguilles
paint.Begin($hPicture) '<---------------------------------------' début de la peinture

options()'<-------------------------------------------------------' Les options avant le reste pour ne pas couvir les aiguilles

iRadius = $iHandLength[iDesign] '<-------------------------------' Base length of the clock hands

'<----------------------------------------------------------------' Hour Hand
Winkel = (Hour(temps) * pk - 90 + 0.5 * Minute(temps)) * rp'<-----' Angle of the hour hand in degrees
x = (iRadius * m) * Cos(Rad(Winkel)) '<-------------------------' X-co-ordinate, conversion of degrees to radian
y = (iRadius * m) * Sin(Rad(Winkel)) '<-------------------------' Y-co-ordinate, conversion of degrees to radian
Zeichnen(x, y, $cHandColor[iDesign], 6, W, H)
'<----------------------------------------------------------------' partie opposée aiguille heure
Winkel = (Hour(temps) * pk + 90 + 0.5 * Minute(temps)) * rp
x = ((iRadius * m) * Cos(Rad(Winkel))) * c
y = ((iRadius * m) * Sin(Rad(Winkel))) * c
Zeichnen(x, y, $cHandColor[iDesign], 7, W, H)
'<----------------------------------------------------------------' Minute Hand
Winkel = (Minute(temps) * p - 90) * rp
x = (iRadius - 3) * Cos(Rad(Winkel))
y = (iRadius - 3) * Sin(Rad(Winkel))
Zeichnen(x, y, $cHandColor[iDesign], 3, W, H)
'<----------------------------------------------------------------' partie opposée aiguille minute
Winkel = (Minute(temps) * p + 90) * rp
x = (iRadius - 3) * Cos(Rad(Winkel)) * c
y = (iRadius - 3) * Sin(Rad(Winkel)) * c
Zeichnen(x, y, $cHandColor[iDesign], 4, W, H)

IF bTrotteuse THEN
'<-------------------------------------------------------------' Second Hand
Winkel = (Second(temps) * p - 90) * rp
x = iRadius * Cos(Rad(Winkel))
y = iRadius * Sin(Rad(Winkel))
Zeichnen(x, y, Color.Red, 2, W, H)
'<-------------------------------------------------------------' opposit part (short) of the Second Hand
Winkel = (Second(temps) * p + 90) * rp
x = iRadius * Cos(Rad(Winkel)) * c
y = iRadius * Sin(Rad(Winkel)) * c
Zeichnen(x, y, Color.Red, 3, W, H)
'<-------------------------------------------------------------' Draws a center circle marque le centre
paint.Brush = paint.Color(Color.Red)
paint.Arc(W / 2, H / 2, 6) ' <---------------------------------' peindre un arc au milieu de rayon
paint.Fill
'<-------------------------------------------------------------' Draws the center point marque le centre
paint.Brush = paint.Color($cHandColor[iDesign])
paint.Arc(W / 2, H / 2, 5) ' <---------------------------------' peindre un arc au milieu de rayon
paint.Fill
ELSE
'<-------------------------------------------------------------' Draws the center point marque le centre
paint.Brush = paint.Color($cHandColor[iDesign])
paint.Arc(W / 2, H / 2, 5) ' <---------------------------------' peindre un arc au milieu de rayon
paint.Fill
ENDIF

paint.End '<----------------------------------------------------' fin de la peinture
PictureBox1.Picture = $hPicture '<------------------------------' Transfer painted picture to PictureBox

END

Le design de la montre :
1
2
3
4
5
6
7
8
PRIVATE SUB SetDesign(i AS INTEGER) '<-------------------------------' action sur l'item du menu cliqué

iDesign = i
ME.Picture = Picture.Load("Images/Gambas_Clock_" & Format(iDesign, "0") & ".png") '<----'choix de l'image
PaintClock(Now) '<----------------------------------------------' mise à jour de l'horloge
Module_Settings.StoreClockSettings() '<-------------------------' sauvegarde des settings

END

Instanciation :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PUBLIC SUB _new()

$hConsoleTimer = NEW Timer AS "Timer1"
$hConsoleTimer.Delay = 1000
$hConsoleTimer.Enabled = TRUE

paramAiguilles() '<-----------------------------------------------' affichage des aiguilles de l'horloge
dimPicture1() '<-------------------------------------------------' dimensions de la pictureBox1

WITH ME
.mask = TRUE '<----------------------------------------------' mask transparent du formulaire, ne fonctionne pas sous wayland
.w = pictureBox1.w
.h = pictureBox1.h
.SkipTaskbar = TRUE
END WITH

END

Ouverture du formulaire principal :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
PUBLIC SUB Form_Open()

Module_Settings.InitDefaultPath '<-------------------------------' Initializing the default path for storing the time zone settings
Module_Settings.RestoreClockSettings() '<-------------------------' Restore clock design
Module_Settings.RestoreFormPosition(ME) '<----------------------' Restore Form positions

IF NOT Settings.Exist("Clock" & "/Design") THEN '<----------------' affichage premir démarrage
iDesign = 0 '<-------------------------------------------------' Design_0 au 1er démarrage
iDrap = 0 '<-------------------------------------------------' pas d'affichage de texte au 1er démarrage
ENDIF

ME.Picture = Picture.Load("Images/Gambas_Clock_" & Format(iDesign, "0") & ".png") '<-------' chargement du fond de l'horloge

IF NOT Settings.Exist("Clock" & "/Trotteuse") THEN
bTrotteuse = TRUE '<-----------------------------------------' pour avoir la trotteuse au démarrage
ENDIF

IF NOT Settings.Exist("Clock" & "/Texte1") THEN
sText1 = "Gambas"
ENDIF

IF NOT Settings.Exist("Clock" & "/Texte2") THEN
sText2 = "Buch"
ENDIF

IF NOT Settings.Exist("Clock" & "/bAuto") THEN
bAuto = FALSE
ENDIF

$hConsoleTimer.trigger'<------------------------------------------' Updating the time display at program start

END

les actions de la souris sur menu contextuel :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
PUBLIC SUB PictureBox1_MouseDown()

DIM hContext AS OBJECT '<----------------------------------------' on peut les rendre Static Public
DIM hContext1 AS OBJECT '<---------------------------------------' on peut les rendre Static Public
DIM hContext2 AS OBJECT '<---------------------------------------' on peut les rendre Static Public
DIM hContext3 AS OBJECT '<---------------------------------------' on peut les rendre Static Public
DIM hMenuItem AS OBJECT '<---------------------------------------' on peut les rendre Static Public

DIM i AS INTEGER '<----------------------------------------------' variable vraiment locale

hContext = NEW Menu(ME) AS "mnuContext" '<------------------------' menu contextuel principal

hContext2 = NEW Menu(hContext) '<------------------------------' menu contextuel secondaire
hContext2.Text = ("Design")
hContext2.Picture = Picture["Images/Gambas_Clock_1.png"]

hContext1 = NEW Menu(hContext) '<------------------------------' menu contextuel secondaire
hContext1.Text = ("Affichage")
hContext1.Picture = Picture["Symbols/clock.png"]

hContext3 = NEW Menu(hContext) '<------------------------------' menu contextuel secondaire
hContext3.Text = ("Autres")
hContext3.Picture = Picture["icon:/32/administrator"]

hMenuItem = NEW Menu(hContext) AS "mnuEnreg" '<---------------' menu contextuel secondaire
hMenuItem.Text = ("Enregistrement")
hMenuItem.Picture = Picture["icon:/32/floppy"]
hMenuItem.Action = "Enreg"

hMenuItem = NEW Menu(hContext) '<-------------------------------' ligne marquée dans menu
hMenuItem.Text = ("")

hMenuItem = NEW Menu(hContext) AS "mnuExit" '<---------------' menu contextuel secondaire
hMenuItem.Text = ("Sortie")
hMenuItem.Picture = Picture["icon:/32/close"]
hMenuItem.Action = "Exit"

FOR i = 0 TO 4

hMenuItem = NEW Menu(hContext1) AS "Option"
hMenuItem.Tag = Format(i, "0")

SELECT CASE i
CASE 0
hMenuItem.Text = ("Nothing ") '<-----------------------' texte du menu en fonction de l'option
hMenuItem.Picture = Picture["icon:/48/cancel"]
hMenuItem.Action = ""
CASE 1
hMenuItem.Text = ("Text ")
hMenuItem.Picture = Picture["icon:/48/font"]
hMenuItem.Action = ""
CASE 2
hMenuItem.Text = ("Date ") '<-------------------------' texte du menu en fonction de l'option
hMenuItem.Picture = Picture["icon:/48/restaurant"]
hMenuItem.Action = ""
CASE 3
hMenuItem.Text = ("Logo ") '<-------------------------' Logo du menu en fonction de l'option
hMenuItem.Picture = Picture["icon:/32/gambas"]
hMenuItem.Action = ""
CASE 4
hMenuItem.Text = ("Date et Logo ") '<-----------------' Logo du menu en fonction de l'option
hMenuItem.Picture = Picture["icon:/32/gambas"]
hMenuItem.Action = ""

END SELECT

IF iDrap = i THEN hMenuItem.Checked = TRUE

NEXT

hMenuItem = NEW Menu(hContext3) AS "mnuReveil"
hMenuItem.Text = ("Réveil"
hMenuItem.Picture = Picture["icon:/32/alarm"]
hMenuItem.Action = "Reveil"

hMenuItem = NEW Menu(hContext3) AS "mnuTrotteuse"
hMenuItem.Text = ("Trotteuse ")
hMenuItem.Picture = Picture["icon:/32/clock"]
hMenuItem.Action = "Trotteuse"

hMenuItem = NEW Menu(hContext3) AS "mnuAuto"
hMenuItem.Text = ("Auto ")
hMenuItem.Picture = Picture["icon:/32/car"]
hMenuItem.Action = "Auto"
hMenuItem.Tag = "Auto"
IF bAuto THEN hMenuItem.Checked = TRUE '<-------------------------' check sur menu Auto en fonction bAuto

hMenuItem = NEW Menu(hContext3)
hMenuItem.Text = ("")

hMenuItem = NEW Menu(hContext3) AS "mnuHelp"
hMenuItem.Text = ("Aide")
hMenuItem.Picture = Picture["icon:/32/help"]
hMenuItem.Action = "Help"

FOR i = 0 TO $iNbreImage'<----------------------------------------' Generate the menu items
hMenuItem = NEW Menu(hContext2) AS "mnuDesign"
hMenuItem.Picture = Picture["Images/Gambas_Clock_" & Format(i, "0") & ".png"]
hMenuItem.Action = "clock-design_" & Format(i, "0")
hMenuItem.Tag = Format(i, "0")
hMenuItem.Text = ("Design " & Format(i, "0")) '<-------------' texte du menu en fonction de i
IF iDesign = i THEN hMenuItem.Checked = TRUE
NEXT

IF Mouse.Right THEN
hContext.Popup '<----------------------------------------------' affichage contextuel du menu avec les items créés ici
ENDIF

END

Action du Timer :
1
2
3
4
5
6
7
8
9
10
11
12
13
PUBLIC SUB Timer1_Timer() '<----------------------------------------' mais que fait le Timer

PaintClock(Now) '<----------------------------------------------' il repeint les aiguilles toutes les secondes

IF bAuto THEN '<--------------------------------------------------' changement d'image automatique
IF Second(Now) MOD 15 = 0 THEN
SetDesign($iCount)
INC $iCount
IF $iCount > $iNbreImage THEN $iCount = 0
ENDIF
ENDIF

END

Autres procédures :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
PUBLIC SUB mnuEnreg_Click() '<---------------------------------------' automatique ou non

Module_Settings.StoreFormPosition(ME) '<-------------------------' sauvegarde avant fermeture
Module_Settings.StoreClockSettings()

END

PUBLIC SUB mnuAuto_Click() '<----------------------------------------' automatique ou non

bAuto = NOT bAuto
$iCount = iDesign '<----------------------------------------------' mise à jour compteur pour auto
Module_Settings.StoreClockSettings() '<-------------------------' sauvegarde des settings

END

PUBLIC SUB mnuTrotteuse_Click()

bTrotteuse = NOT bTrotteuse
PaintClock(Now)
Module_Settings.StoreClockSettings() '<-------------------------' sauvegarde des settings

END

PUBLIC SUB mnuHelp_Click()

FHelp.Show

END

PUBLIC SUB mnuReveil_Click()

Alarm.Show

END

PUBLIC SUB mnuExit_Click()

Module_Settings.StoreFormPosition(ME) '<-------------------------' sauvegarde avant fermeture
Module_Settings.StoreClockSettings()
ME.Close()

END

PUBLIC SUB option_Click() '<----------------------------------------' récupération de l'option choisie

iDrap = LAST.tag
PaintClock(Now) '<----------------------------------------------' mise à jour de l'horloge

END

PUBLIC SUB mnuDesign_Click()

SetDesign(LAST.Tag)'<---------------------------------------------' Récupération du dernier Item cliqué

END

PUBLIC SUB PictureBox1_MouseDrag() '<-------------------------------' pour draguer

ME.x += Mouse.x - Mouse.startx
ME.y += Mouse.y - Mouse.starty

END


Explications :



Il s'agit d'une horloge analogique utlisant un formulaire transparent, une image normée en dimension du fond de l'horloge avec les aiguilles créées par code.
Les Settings sont utilisés pour conserver choix du fond de l'horloge ainsi que position de celle-ci sur l'écran.
Ça donne un truc comme ça, avec le menu contextuel :





====================

Navigation :



<-- Liens du Wiki : <--
<-- Accueil du WIKI : <--

====================

Documentation :



==============================