Création d'une calculatrice pour vos applications Access

Jean-Philippe AMBROSINO

Ce document a pour but de vous montrer comment concevoir une petite calculatrice sous Access.
Vous devez être à l'aise avec Microsoft Access et impérativement maîtriser la conception de formulaires ainsi que connaître le langage Visual Basic for Application pour mettre en pratique cet exemple.

Commentez

- Titre : Création d'une calculatrice pour vos applications Access

- Auteur : Jean-Philippe AMBROSINO

- Parution : 15 mai 2006

- Mise à jour : 15 mai 2006

- Licence : Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Avant-propos

- I-A. Remerciements

- I-B. Contact

- II. Présentation du projet

- III. Présentation du formulaire exemple

- III-A. Le formulaire en mode formulaire

- III-B. Les propriétés du formulaire

- IV. Le formulaire en mode création

- IV-A. Détail des contrôles utilisés

- IV-A-1. La partie application

- IV-A-1-a. Les messages circonstanciels à l'usage du mode d'affichage

- IV-A-1-b. Les boutons des fonctions d'application

- IV-A-2. La partie calculatrice

- IV-A-2-a. Liste des contrôles utilisés avec leur nom et position (en pixels)

- V. Le code de la calculatrice

- V-A. Le projet est constitué de deux modules de code

- V-A-1. Le code du formulaire

- V-A-2. Le code du Module basRegistry

- VI. Comment cela fonctionne-t-il ?

- VII. Comment l'utiliser ?

- VII-A. Elle est ouverte, mais je ne peux pas la déplacer !!!

- VIII. Conclusion

I - Avant-propos

Ce document a pour but de vous montrer comment concevoir une petite calculatrice sous Access.
En effet, vous pouvez appeler la calculatrice de Windows, mais cette opération vous oblige à vérifier si elle n'est pas déjà lancée, auquel cas, il vous faut l'afficher au premier plan (donc, être à l'aise les API Windows).
Là, aucun problème de ce côté puisqu'il s'agit d'un formulaire et seules les fonctions de base d'ouverture (DoCmd.OpenForm) et de fermeture (DoCmd.Close) sont nécessaires.

I-A - Remerciements

Je tiens à remercier toutes celles et tous ceux qui ont participé à la relecture de ce document en y incluant leurs remarques.

I-B - Contact

Pour tous renseignements complémentaires, veuillez me contacter directement (Argyronet) par MP.

II - Présentation du projet

L'objectif de ce tutoriel est de vous montrer qu'il est possible de concevoir une petite calculatrice d'appoint parfaitement opérationnelle dans votre application Access.

Cette calculatrice offre toutes les fonctions de base y compris la mémoire (+/-) avec un convertisseur euros/francs en temps réel au fur et à mesure des entrées et résultats affichés. Bon, je vous l'accorde, ce n'est pas forcément très utile, mais il s'avère que son usage devient vite pratique si des boutons permettant de l'appeler au moment voulu sont correctement posés dans vos formulaires.

Autre avantage, les calculs trouvés, en dehors du fait que j'ai prévu une routine de copier/coller automatique, peuvent se trouver recopiés dans une zone de texte d'un formulaire parent ou plutôt du formulaire appelant par la ligne de code suivante :

Recopier le résultat trouvé

Forms!NomDuFormulaireParent.NomDuContrôle = Me!txtLCDDisplayEUR

où bien entendu, txtLCDDisplayEUR est le nom du contrôle affichant le résultat dans la calculatrice ;
(nous verrons les noms des contrôles un peu plus loin).

III - Présentation du formulaire exemple

Réaliser une calculatrice d'un point de vue graphique n'est pas très difficile en soi ; il suffit de s'inspirer de sa calculatrice de bureau ou d'une photo idoine représentative…
Le reste se réalise en fonction de vos goûts et en fonction des besoins. Dans ce tutoriel, la calculatrice possède un certain nombre de boutons associés à différentes fonctionnalités et vous n'êtes pas tenu de les greffer tous.

III-A - Le formulaire en mode formulaire

Vous pouvez constater que ce formulaire est volontairement dépourvu du sélecteur et du diviseur d'enregistrements.
J'ai également pour les mêmes raisons d'esthétique, supprimé les boutons de déplacement.

Une fois appelé, il s'ouvre au premier plan en mode Modal, c'est-à-dire, que vous ne pouvez pas intervenir sur le formulaire qui l'a ouvert tant que celui-ci reste affiché.
Comme je suis un peu maniaque, j'ai greffé à la calculatrice un petit bouton permettant à volonté de changer cet état Modal en non Modal pour des raisons pratiques.

Le formulaire en mode formulaire

Pour le côté graphique, le formulaire voit sa propriété Image affectée à une image dégradée d'un bleu violet tirant en un écru grisonnant, charte graphique adoptée à l'époque où j'ai créé l'application qui employait cette calculatrice.

Pour créer cette image ou tout autre arrière-plan de votre convenance, prenez un logiciel de retouche d'images (The Gimp, PaintShop Pro, Photoshop…), mettez en œuvre une forme rectangulaire de 100 x 332 pixels puis appliquez-lui le dégradé désiré si vous avez choisi d'opter pour un tel arrière-plan

Rognez ensuite l'image de telle sorte que sa taille devienne 1 x 332 pixels et dans les propriétés Mode d'affichage de l'image du formulaire, choisissez Échelle ; le rendu du dégradé sera répété sur toute la largeur de la section Détail du formulaire.

Merci à cafeine pour cette remarque…

Sauvez l'image au format BMP ou JPG dans le dossier \Images de votre application.

III-B - Les propriétés du formulaire

Liste récapitulative des propriétés à affecter au formulaire

Ce formulaire, pour pouvoir être affiché ainsi, possède donc les propriétés suivantes :

Propriétés générales

Propriétés des événements

Pour afficher les propriétés du formulaire, cliquez deux fois sur la zone externe gris foncé de votre environnement Access ou bien sur le bouton Propriétés de la barre d'outils.
Cliquez alors sur l'onglet intitulé « Toutes » puis « Événements ».

TRÈS IMPORTANT

N'oubliez pas de définir à Oui, la propriété Aperçu des touches (Key Preview) sans quoi, vous ne pourrez pas utiliser la calculatrice avec le clavier…

IV - Le formulaire en mode création

Lorsque l'on passe en Mode Création, vous pouvez remarquer qu'il n'y a pas grandes différences avec le mode formulaire.
Le projet exploite 47 contrôles différents parmi lesquels figurent :

des Boutons

des Zones de texte

des Étiquettes

des Rectangles

Vous en trouverez la liste ci-après.

Le formulaire en mode création (Design)

Du fait que la mise en place de ces contrôles nécessite une certaine précision, je vous recommande de ne pas afficher la Grille que vous désactivez dans le menu Affichage.

Petite astuce

Les touches de raccourci Ctrl+Flèche de direction déplacent un contrôle ou un groupe de contrôles au pixel près.

Les touches de raccourci Shift+Flèche de direction agrandissent/rétrécissent un contrôle ou un groupe de contrôles au pixel près.

IV-A - Détail des contrôles utilisés

Il y a deux parties à considérer pour la réalisation de ce projet :
- 1/ la partie application ;
- 2/ la partie calculatrice.

IV-A-1 - La partie application

La partie dite « application » relate ce que je considère comme étant les fonctions externes au formulaire lui-même.
En effet, ces fonctions sont représentées par les trois boutons qui sont respectivement :

- Copier (Ctrl+C) ;

- Coller (Ctrl+V) ;

- Premier plan/Arrière-plan.

Vous pouvez constater que trois rectangles de couleur rouge sont leur support.
J'ai posé ces contrôles tout simplement pour indiquer l'état de l'emploi des boutons :

- Rouge : inactif ou non disponible ;

- Vert : activé ou enclenché.

Dans le code, ces rectangles voient leur propriété BackColor changer en conséquence.

Code du changement des couleurs des rectangles

ledCopy.BackColor = RGB(0, 255, 0) ' Vert
ledPaste.BackColor = RGB(255, 0, 0) ' Rouge

Le 3e bouton quant à lui est un peu particulier parce qu'il masque ou affiche son « conjoint » en conséquence de l'état de la fenêtre :

son conjoint est bien évidemment un autre bouton illustré différemment. J'ai préféré cette méthode plutôt que l'affectation dynamique de l'image (qui nécessite que l'image soit dans un dossier en tant que fichier), mais rien ne vous empêche de faire comme bon vous semble pour ce cas précis.

Mode non Modal

Mode Modal

Mode non Modal : l'accès au formulaire appelant est libre :
il faudra appuyer de nouveau sur le bouton ouvrant la calculatrice si le formulaire appelant occupe tout l'écran.

Mode Modal : il est nécessaire de fermer la calculatrice pour avoir la main sur le formulaire appelant :
le mode Modal est affecté par défaut au formulaire.

IV-A-1-a - Les messages circonstanciels à l'usage du mode d'affichage

J'ai greffé au projet deux affichages de message avec la fonction MsgBox() qui annoncent respectivement l'état de la calculatrice selon le mode choisi :

Avertissement de désactivation du mode Modal

Avertissement de l'activation du mode Modal

IV-A-1-b - Les boutons des fonctions d'application

Vous dessinerez donc trois Rectangles identiques au format 3D enfoncé avec par défaut, la couleur de fond rouge.

Détail des contrôles utilisés pour les actions de Copier/Coller et du Mode fenêtre

Les boutons du mode d'affichage sont superposés ;

- le bouton Mode Modal est au premier plan et possède la propriété Visible définie à True ;

- l'autre bouton Mode non Modal possède bien entendu la propriété Visible définie à False et se trouve sur la couche du milieu.

(Entre le Rectangle et le bouton du premier plan.)

IV-A-2 - La partie calculatrice

C'est de loin la mise en place la plus délicate, car elle nécessite de la minutie et de la patience…
L'idéal est de dessiner un bouton pour la partie bouton par exemple et de le dupliquer autant de fois que nécessaire, c'est-à-dire 27 fois…

Dans un premier temps, posez-les de façon approximative, mais régulière. L'ajustement se fait soit à l'aide des données de propriétés par les propriétés Haut (Top) et Gauche (Left) ou bien comme précisé ci-avant, à l'aide des raccourcis clavier.

Affectez à chacun d'entre eux la légende appropriée.

Seul le bouton Racine Carrée possède une police Symbole, car je n'avais pas trouvé à l'époque le symbole idoine et j'avais triché avec cette méthode en entrant les caractères Öa.

(Ceci dit, rien ne vous empêche de mettre des images pour chacun des boutons.)

Tous les autres boutons sont définis en police Arial 12 et colorés en noir pour les chiffres et en différentes couleurs pour les fonctions particulières comme l'illustre la première image.

Vous dessinerez en suite les rectangles puis les zones de texte.

=> La zone de texte affichant la valeur en euros - ou plus exactement le résultat trouvé en fait - est définie en Arial 18 Noir avec un fond gris clair et comme Valeur par défaut « 0 ».

=> La zone de texte affichant la valeur en francs est définie en Arial 11 Gris foncé avec un fond gris clair et comme Valeur par défaut « 0 ».

Elles sont toutes les deux justifiées à Gauche.

=> Quatre étiquettes (Label) sont dessinées à gauche de chaque afficheur et recevant respectivement la propriété Intitulé (Caption) avec les caractères € en Arial 16 Italique et F en Arial 10 Italique avec les couleurs Bleu au-dessus du Violet.

=> Deux zones de texte nommées txtPasteData et txtHiddenFinalResult possèdent la propriété Visible à False et sont destinées à recevoir respectivement les informations du presse-papier de façon temporaire et le calcul en cours avant de l'afficher.

IV-A-2-a - Liste des contrôles utilisés avec leur nom et position (en pixels)

Je vous recommande (comme je l'ai stipulé dans ce tutoriel) de nommer tous les contrôles, même ceux qui ne sont pas utilisés dans le code.
Cela est bien plus pratique pour vous comme pour tout autre développeur qui reprendrait éventuellement votre projet.

Détail des contrôles utilisés pour les rectangles, zones de texte et images

Vous trouverez ci-dessous, la liste récapitulative des contrôles du formulaire avec leur position en pixels…

Pour ceux d'entre vous qui le souhaitent, vous pouvez très bien mettre en place une procédure de conception du formulaire avec les méthodes Add de l'objet Control ; de ce fait, vous n'aurez plus qu'un minimum de travail à faire…

Tableau récapitulatif des contrôles utilisés avec leur position

Objet

Type de contrôle

Nom du contrôle

Position horizontale

Position verticale

Largeur

Hauteur

Bouton 0

104

btn0

x:375

y:3150

w:945

h:397

Bouton 1

104

btn1

x:375

y:2640

w:450

h:397

Bouton 2

104

btn2

x:877

y:2640

w:450

h:397

Bouton 3

104

btn3

x:1366

y:2640

w:450

h:397

Bouton 4

104

btn4

x:375

y:2130

w:450

h:397

Bouton 5

104

btn5

x:877

y:2130

w:450

h:397

Bouton 6

104

btn6

x:1366

y:2130

w:450

h:397

Bouton 7

104

btn7

x:375

y:1635

w:450

h:397

Bouton 8

104

btn8

x:877

y:1635

w:450

h:397

Bouton 9

104

btn9

x:1365

y:1635

w:450

h:397

Bouton +

104

btnAdd

x:1920

y:2130

w:500

h:397

Bouton C

104

btnC

x:1920

y:1635

w:500

h:397

Bouton CE

104

btnCE

x:2505

y:1635

w:500

h:397

Bouton ,

104

BtnDec

x:1366

y:3150

w:450

h:397

Bouton ÷

104

btnDivide

x:1920

y:3675

w:500

h:397

Bouton =

104

btnEqual

x:1366

y:3675

w:450

h:397

Bouton 1/x

104

btnInvert

x:2505

y:2640

w:500

h:397

Bouton MC

104

btnMemClear

x:3075

y:2647

w:470

h:397

Bouton M-

104

btnMemLess

x:3075

y:2130

w:470

h:397

Bouton M+

104

btnMemMore

x:3075

y:1635

w:470

h:397

Bouton MR

104

btnMemRecall

x:3075

y:3150

w:470

h:922

Bouton X

104

btnMult

x:1920

y:3150

w:500

h:397

Bouton On/Off

122

btnOnOff

x:405

y:3720

w:870

h:307

Bouton %

104

btnPercent

x:2505

y:3150

w:500

h:397

Bouton Vx

104

btnSQRT

x:2505

y:2130

w:500

h:397

Bouton -

104

btnSubst

x:1920

y:2640

w:500

h:397

Bouton X²

104

btnX2

x:2505

y:3675

w:500

h:397

Bouton Copier

103

cmdCopy

x:2340

y:4305

w:315

h:334

Bouton Mode non modal

103

cmdNoTopMost

x:3195

y:4305

w:330

h:330

Bouton Coller

103

cmdPaste

x:2768

y:4305

w:315

h:334

Bouton Mode modal

103

cmdTopMost

x:3195

y:4305

w:315

h:334

Rectangle des boutons du bas

103

imgAppButtons

x:240

y:4140

w:3390

h:630

Étiquette € bleue

100

lblCurrency01

x:150

y:300

w:255

h:465

Étiquette € violette

100

lblCurrency02

x:135

y:285

w:255

h:465

Étiquette F bleue

100

lblFRF1

x:165

y:990

w:195

h:285

Étiquette F violette

100

lblFRF2

x:180

y:1005

w:195

h:285

Rectangle Copier

101

ledCopy

x:2295

y:4260

w:405

h:420

Rectangle Coller

101

ledPaste

x:2723

y:4260

w:421

h:420

Rectangle Mode

101

ledTopMost

x:3151

y:4260

w:405

h:420

Rectangle grand cadre

101

shpCalc1

x:90

y:90

w:3673

h:4822

Rectangle moyen cadre

101

shpCalc2

x:225

y:1530

w:3405

h:3255

Rectangle cadre de l'afficheur Euro

101

shpEuroDisplayer

x:405

y:165

w:3255

h:615

Rectangle cadre de l'afficheur FRF

101

shpFRFDisplayer

x:405

y:960

w:3255

h:435

Rectangle du bouton On/Off

101

shpLED

x:375

y:3690

w:930

h:360

Rectangle trait de séparation

101

shpSeparator

x:120

y:855

w:3630

h:45

Zone de texte Afficheur Euro

109

txtLCDDisplayEUR

x:465

y:225

w:3135

h:495

Zone de texte Afficheur FRF

109

txtLCDDisplayFRF

x:465

y:1020

w:3135

h:315

V - Le code de la calculatrice

Bien que cela semble être on ne peut plus simple de comprendre les fonctions de base d'une calculatrice, il faut considérer qu'un certain nombre de lignes de code est nécessaire à son bon fonctionnement.
Bien entendu, les fonctions de base d'additions, de soustractions, de multiplications et de divisions restent les plus simples.

L'usage de deux variables tampons qui subissent un changement de résultat en fonction de l'opérateur choisi.
Pour mettre en œuvre les gestions des opérateurs, il y a plusieurs manières de procéder. J'ai, pour ce projet, choisi l'usage d'une variable de type String qui prend la valeur idoine en fonction du fait que j'appuie sur un chiffre, une virgule ou un opérateur…

Cette variable nommée « m_strLastFlagEntry » reçoit les valeurs suivantes :

Valeur reçue

Description

C

L'utilisateur a appuyé sur C

CE

L'utilisateur a appuyé sur C

ActionIsOperator

L'utilisateur a appuyé sur un opérateur

ActionIsNumber

L'utilisateur a appuyé sur un chiffre

ActionIsNothing

Aucune action (équivaut à vbNullString)

V-A - Le projet est constitué de deux modules de code

Le code associé à ce projet est réparti dans deux modules ; le premier étant bien entendu le module de classe du formulaire lui-même et l'autre étant un module de projet avec une fonction pour lire dans la base de registre…

V-A-1 - Le code du formulaire

L'ensemble du code ci-après est à recopier dans le module du formulaire…

Dans l'en-tête sont déclarées des variables de module ainsi qu'une fonction API

En-tête de Module du formulaire

''' ************************************************************************************
'''     PROJECT NAME  :   Calculator for MS Access Applications
'''     MODULE NAME   :   frmCalculator
'''     AUTHOR        :   Jean-Philippe AMBROSINO
'''     CONTACT       :   http://cerbermail.com/?wDzGFhHk1g
'''
'''     PUBLISHED ON  :   http://access.developpez.com/
'''
''' ************************************************************************************

Option Compare Database
Option Explicit

Private m_dblFirstEntry As Double
Private m_dblSecondEntry As Double
Private m_blnWithDecimal As Integer
Private m_blnOperationNumber As Integer
Private m_strLastFlagEntry As String
Private m_strFlagOperator As String
Private m_vntTotalDisplayed As Variant
Private m_intMaxDigit As Integer
Private m_dblBufferMemory As Double

Private m_vntFinalResult As Double
Private m_dblEuroValue As Double

Private m_strSeparator As String

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Les boutons gèrent toujours les mêmes événements

Code des boutons 1 à 9 et , et =

Private Sub btn0_Click()
''' Bouton 0 appuyé
'''------------------------
FlagActionButtons "0"
KeepFocus "btn0"
ConvertToFRF
End Sub

Private Sub btn1_Click()
''' Bouton 1 appuyé
'''------------------------
FlagActionButtons "1"
KeepFocus "btn1"
ConvertToFRF
End Sub
Private Sub btn2_Click()
''' Bouton 2 appuyé
'''------------------------
FlagActionButtons "2"
KeepFocus "btn2"
ConvertToFRF
End Sub

Private Sub btn3_Click()
''' Bouton 3 appuyé
'''------------------------
FlagActionButtons "3"
KeepFocus "btn3"
ConvertToFRF
End Sub

Private Sub btn4_Click()
''' Bouton 4 appuyé
'''------------------------
FlagActionButtons "4"
KeepFocus "btn4"
ConvertToFRF
End Sub

Private Sub btn5_Click()
''' Bouton 5 appuyé
'''------------------------
FlagActionButtons "5"
KeepFocus "btn5"
ConvertToFRF
End Sub

Private Sub btn6_Click()
''' Bouton 6 appuyé
'''------------------------
FlagActionButtons "6"
KeepFocus "btn6"
ConvertToFRF
End Sub

Private Sub btn7_Click()
''' Bouton 7 appuyé
'''------------------------
FlagActionButtons "7"
KeepFocus "btn7"
ConvertToFRF
End Sub

Private Sub btn8_Click()
''' Bouton 8 appuyé
'''------------------------
FlagActionButtons "8"
KeepFocus "btn8"
ConvertToFRF
End Sub

Private Sub btn9_Click()
''' Bouton 9 appuyé
'''------------------------
FlagActionButtons "9"
KeepFocus "btn9"
ConvertToFRF
End Sub

Private Sub btnDec_Click()
''' Bouton , appuyé
'''------------------------
If m_strLastFlagEntry <> "ActionIsNumber" Then
Me!txtLCDDisplayEUR = "0" & m_strSeparator
ElseIf m_blnWithDecimal = False Then
Me!txtLCDDisplayEUR = Me!txtLCDDisplayEUR & m_strSeparator
m_intMaxDigit = m_intMaxDigit + 1
End If

m_blnWithDecimal = True
m_strLastFlagEntry = "ActionIsNumber"
End Sub

Private Sub btnEqual_Click()
''' Bouton = appuyé
'''------------------------
FunctionOperator "="
m_intMaxDigit = 0
KeepFocus "btnEqual"
ConvertToFRF
End Sub

Les opérations sont gérées par une seule fonction qui est appelée systématiquement

Code des boutons des opérateurs + - x ÷

Private Sub btnAdd_Click()
''' Bouton + appuyé
'''------------------------
FunctionOperator "+"
m_intMaxDigit = 0
KeepFocus "btnAdd"
ConvertToFRF
End Sub

Private Sub btnSubst_Click()
''' Bouton - appuyé
'''------------------------
FunctionOperator "-"
m_intMaxDigit = 0
KeepFocus "btnSubst"
ConvertToFRF
End Sub

Private Sub btnDivide_Click()
''' Bouton / appuyé
'''------------------------
FunctionOperator "/"
m_intMaxDigit = 0
KeepFocus "btnDivide"
End Sub

Private Sub btnMult_Click()
''' Bouton X appuyé
'''------------------------
FunctionOperator "*"
m_intMaxDigit = 0
KeepFocus "btnMult"
ConvertToFRF
End Sub

Les boutons d'annulation annulent le contenu des variables et celui d'extinction change la propriété BackColor puis appelle la fonction KeepCurrentResult.

Code des boutons des fonctions spéciales C CE On/Off

Private Sub btnC_Click()
''' Bouton C appuyé
'''------------------------
Me!txtLCDDisplayEUR = "0" & m_strSeparator
Me!txtLCDDisplayFRF = "0" & m_strSeparator
m_blnWithDecimal = False
m_strLastFlagEntry = "C"
KeepFocus "btnC"
m_intMaxDigit = 0
m_dblEuroValue = 0
End Sub

Private Sub btnCE_Click()
''' Bouton CE appuyé
'''------------------------
m_strLastFlagEntry = "CE"
KeepFocus "btnCE"
End Sub

Private Sub btnOnOff_Click()
''' Bouton On/Off appuyé
'''------------------------
btnOnOff.Caption = "O F F"
btnOnOff.ForeColor = RGB(255, 0, 0)
shpLED.BackColor = RGB(255, 0, 0)
DoEvents
Call Sleep(1000)
KeepCurrentResult
End Sub

Les fonctions spéciales exploitent un code aussi simple à comprendre que les opérations de base vues ci-avant.

Code des boutons des fonctions spéciales Vx 1/x % X²

Private Sub btnSQRT_Click()
''' Bouton Vx appuyé
'''------------------------
m_dblFirstEntry = Val(Me!txtLCDDisplayEUR)
If m_dblFirstEntry < 0 Then
MsgBox "La racine carrée d´un nombre négatif n´est pas valable !" & vbCrLf & _
vbCrLf & "Le calcul est impossible", 48, "Erreur"
Else
m_dblFirstEntry = Sqr(m_dblFirstEntry)
m_intMaxDigit = 0
End If
Me!txtLCDDisplayEUR = str$(m_dblFirstEntry)
m_blnOperationNumber = 1
m_strLastFlagEntry = "ActionIsOperator"
m_strFlagOperator = vbNullString
ConvertToFRF
End Sub

Private Sub btnInvert_Click()
''' Bouton 1/x appuyé
'''------------------------
m_dblFirstEntry = Val(Me!txtLCDDisplayEUR)

If m_dblFirstEntry = 0 Then
MsgBox "Cette opération est une division par zéro !" & vbCrLf & vbCrLf & _
"Le calcul est impossible", 48, "Erreur"
Else
m_dblFirstEntry = 1 / m_dblFirstEntry
m_intMaxDigit = 0
End If

Me!txtLCDDisplayEUR = str$(m_dblFirstEntry)
m_blnOperationNumber = 1
m_strLastFlagEntry = "ActionIsOperator"
m_strFlagOperator = vbNullString
KeepFocus "btnInvert"
ConvertToFRF
End Sub

Private Sub btnPercent_Click()
''' Bouton % appuyé
'''------------------------
Me!txtLCDDisplayEUR = Format$(m_dblFirstEntry * Val(Me!txtLCDDisplayEUR) / 100)
m_intMaxDigit = 0
KeepFocus "btnPercent"
ConvertToFRF
End Sub

Private Sub btnX2_Click()
''' Bouton X² appuyé
'''------------------------
On Error GoTo L_ErrOverFow
m_dblFirstEntry = Val(Me!txtLCDDisplayEUR)
m_dblFirstEntry = m_dblFirstEntry * m_dblFirstEntry
m_intMaxDigit = 0
Me!txtLCDDisplayEUR = str$(m_dblFirstEntry)
m_blnOperationNumber = 1
m_strLastFlagEntry = "ActionIsOperator"
m_strFlagOperator = vbNullString
ConvertToFRF

L_ExOverFow:
Exit Sub
L_ErrOverFow:
MsgBox "Vous avez atteint la capacité maximum de calcul du processeur...", 48, "Calcul dépassé"
Resume L_ExOverFow
End Sub

La gestion de la mémoire s'effectue tout simplement avec une variable de module.

Code des boutons de mise en mémoire

Private Sub btnMemClear_Click()
''' Bouton MC appuyé
'''------------------------
If m_dblBufferMemory Then
If MsgBox("Effacer le contenu de la mémoire maintenant ?", 52, "Effacer") = 6 Then
m_dblBufferMemory = 0
End If
End If
End Sub

Private Sub btnMemLess_Click()
''' Bouton M- appuyé
'''------------------------
m_dblBufferMemory = m_dblBufferMemory - Me!txtLCDDisplayEUR
End Sub

Private Sub btnMemMore_Click()
m_dblBufferMemory = m_dblBufferMemory + Me!txtLCDDisplayEUR
End Sub

Private Sub btnMemRecall_Click()
''' Bouton MR appuyé
'''------------------------
Me!txtLCDDisplayEUR = vbNullString
Me!txtLCDDisplayEUR = str(m_dblBufferMemory)
End Sub

Au sein du formulaire sont gérés les événements et plus particulièrement celui qui est généré par le clavier.

Code des procédures événementielles du formulaire

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
''' Gestion des touches du clavier
'''------------------------
Select Case KeyCode
Case 96, 48: btn0_Click
Case 97, 49: btn1_Click
Case 98, 50: btn2_Click
Case 99, 51: btn3_Click
Case 100, 52: btn4_Click
Case 101, 53: btn5_Click
Case 102, 54: btn6_Click
Case 103, 55: btn7_Click
Case 104, 56: btn8_Click
Case 105, 57: btn9_Click
Case 110: btnDec_Click
Case 111: btnDivide_Click
Case 106: btnMult_Click
Case 107: btnAdd_Click
Case 109: btnSubst_Click
Case 46: btnCE_Click
Case 13: btnEqual_Click
Case 27: InitializeCalculator: btnC_Click
End Select
End Sub

Private Sub Form_Load()
''' Chargement... (intialise le séparateur de décimales)
'''------------------------
m_strSeparator = GetSystemDecimalSeparator()
btnC.SetFocus
End Sub

Private Sub txtLCDDisplayEUR_KeyPress(KeyAscii As Integer)
''' Effet de frappe dans l´afficheur annulé
'''------------------------
KeyAscii = 0
End Sub

Les fonctions de conversions sont nécessaires notamment à cause du séparateur de décimales du système, mais également pour la conversion en francs de la valeur en euros.

Code des fonctions de conversion

Private Sub ConvertToFRF()
''' Procédure de conversion en francs
'''----------------------------------------
Const EURO As Double = 6.55957
Dim dblResultFound As Double

dblResultFound = ConvertToDouble(Me!txtLCDDisplayEUR)
If dblResultFound = 0 Then
Exit Sub
End If
m_dblEuroValue = dblResultFound
dblResultFound = dblResultFound * EURO
dblResultFound = RoundNumber(dblResultFound, 2)
Me!txtLCDDisplayFRF = str$(dblResultFound)
End Sub

Private Function ConvertToDouble(ByVal varValue As Variant) As Double
''' Fonction de conversion en double
'''----------------------------------------
Const CHR_DECIMALSEP_COMMA As String = ","
Const CHR_DECIMALSEP_DOT As String = "."

Dim strNumberSeparator As String
Dim strTempNumber As String
Dim dblResult As Double

If InStr(1, varValue, CHR_DECIMALSEP_COMMA) Then
strTempNumber = Replace(varValue, CHR_DECIMALSEP_COMMA, m_strSeparator, 1, -1, vbTextCompare)
ElseIf InStr(1, varValue, CHR_DECIMALSEP_DOT) Then
strTempNumber = Replace(varValue, CHR_DECIMALSEP_DOT, m_strSeparator, 1, -1, vbTextCompare)
Else
strTempNumber = varValue
End If
dblResult = CDbl(strTempNumber)
ConvertToDouble = dblResult
End Function

Private Function RoundNumber(ByVal NValue As Double, ByVal nDigits As Integer) As Double
''' Fonction d´arrondi à n décimales
'''------------------------------------------------
RoundNumber = Int(NValue * (10 ^ nDigits) + 0.5) / (10 ^ nDigits)
End Function

Les fonctions des actions servent à faire en sorte que les calculs soient effectués selon les touches appuyées.

Code des fonctions et procédures des actions

Private Sub FunctionOperator(ByVal Operator As String)
''' Fonction déterminant l´opérateur choisi
'''----------------------------------------
If m_strLastFlagEntry = "ActionIsNumber" Then
m_blnOperationNumber = m_blnOperationNumber + 1
End If

If m_blnOperationNumber = 1 Then
m_dblFirstEntry = ConvertToDouble(Me!txtLCDDisplayEUR)
ElseIf m_blnOperationNumber = 2 Then
m_dblSecondEntry = ConvertToDouble(Me!txtLCDDisplayEUR)
Select Case m_strFlagOperator
Case "+"
m_dblFirstEntry = m_dblFirstEntry + m_dblSecondEntry
Case "-"
m_dblFirstEntry = m_dblFirstEntry - m_dblSecondEntry
Case "*"
m_dblFirstEntry = m_dblFirstEntry * m_dblSecondEntry
Case "/"
If m_dblSecondEntry = 0 Then
MsgBox "Cette opération est une division par zéro !" & vbCrLf & vbCrLf & _
"Le calcul est impossible", 48, "Erreur"
Else
m_dblFirstEntry = m_dblFirstEntry / m_dblSecondEntry
End If
Case "="
m_dblFirstEntry = m_dblSecondEntry
End Select
Me!txtLCDDisplayEUR = m_dblFirstEntry
m_blnOperationNumber = 1
End If
m_strLastFlagEntry = "ActionIsOperator"
m_strFlagOperator = Operator
End Sub

Sub KeepFocus(ByVal CtrlName As String)
''' Fonction permettant de garder le focus
'''----------------------------------------
Dim oForm As Form
Dim oCtl As Control

Set oForm = Form
Set oCtl = oForm.Controls(CtrlName)
oCtl.SetFocus
Set oCtl = Nothing
Set oForm = Nothing
End Sub

Private Sub InitializeCalculator()
''' Procédure d'initialisation
'''----------------------------------------
m_blnWithDecimal = False
m_blnOperationNumber = 0
m_strLastFlagEntry = "ActionIsNothing"
m_strFlagOperator = vbNullString
End Sub

Private Sub FlagActionButtons(ByVal EnterNum As String)
''' Procédure de gestion des actions
'''----------------------------------------
If m_strLastFlagEntry <> "ActionIsNumber" Then
Me!txtLCDDisplayEUR = vbNullString
Me!txtHiddenFinalResult = 0
m_blnWithDecimal = False
End If
If m_intMaxDigit > 13 Then
Beep
Exit Sub
End If
Me!txtLCDDisplayEUR = Me!txtLCDDisplayEUR + LTrim$(EnterNum)
Me!txtHiddenFinalResult = ConvertToDouble(Me!txtLCDDisplayEUR)
m_intMaxDigit = m_intMaxDigit + 1
m_strLastFlagEntry = "ActionIsNumber"
End Sub

Private Sub KeepCurrentResult()
''' Procédure de mise en mémoire du résultat
'''-----------------------------------------
Const MSG_CLIPBOARD_01 = "Votre résultat "
Const MSG_CLIPBOARD_02 = " est copié en mémoire..."
Const MSG_CLIPBOARD_03 = "Vous pourrez le coller en utilisant les touches Ctrl+V !"
Const MSG_CLIPBOARD_00 = "Copie"
Const MMSG_KEEP_RESULT_01 = "Voulez-vous conserver les résultats de votre calcul pour un usage ultérieur ?"
Const MMSG_KEEP_RESULT_00 = "Conserver le résultat de "

m_vntTotalDisplayed = Val(Me!txtLCDDisplayEUR)

If m_vntTotalDisplayed = 0 Then GoTo L_ExCopyFail
If MsgBox(MMSG_KEEP_RESULT_01, 36, MMSG_KEEP_RESULT_00 & txtLCDDisplayEUR) = 6 Then
DoCmd.GoToControl "txtLCDDisplayEUR"
m_vntFinalResult = ConvertToDouble(Me!txtLCDDisplayEUR)
txtHiddenFinalResult.Visible = True
Me!txtHiddenFinalResult = m_vntFinalResult
txtHiddenFinalResult.SetFocus
txtHiddenFinalResult.SelStart = 0
txtHiddenFinalResult.SelLength = Len(Me!txtHiddenFinalResult)
On Error GoTo L_ErrCopyFail
DoCmd.RunCommand acCmdCopy
MsgBox MSG_CLIPBOARD_01 & m_vntFinalResult & MSG_CLIPBOARD_02 & vbCrLf & _
vbCrLf & MSG_CLIPBOARD_03, , MSG_CLIPBOARD_00
End If
L_ExCopyFail:
DoCmd.Close 2, "frmCalculator"
Exit Sub
L_ErrCopyFail:
MsgBox "Désolé, la copie a échoué...", 48, "Copie"
Resume L_ExCopyFail
End Sub

Les fonctions externes (facultatives) permettent la gestion du Copier/Coller et du mode d'affichage.

Code des autres fonctions (Copier/Coller/Mode) et l'appel au Registre

Private Sub cmdCopy_Click()
''' Bouton Copier appuyé
'''------------------------
m_vntTotalDisplayed = Val(Me!txtLCDDisplayEUR)
If m_vntTotalDisplayed = 0 Then Exit Sub
CopyResultToClipboard
ledCopy.BackColor = RGB(0, 255, 0)
ledPaste.BackColor = RGB(255, 0, 0)
End Sub

Private Sub cmdPaste_Click()
''' Bouton Coller appuyé
'''------------------------
Dim dblPastedValue

txtPasteData.Visible = True
txtPasteData.SetFocus
On Error Resume Next
Application.RunCommand acCmdPaste
dblPastedValue = Me!txtPasteData

If dblPastedValue <> 0 And IsNumeric(dblPastedValue) Then
Me!txtLCDDisplayEUR = dblPastedValue
ConvertToFRF
ledCopy.BackColor = RGB(255, 0, 0)
ledPaste.BackColor = RGB(0, 255, 0)
Else
MsgBox "Aucun résultat valide n´est applicable à l´afficheur de la calculatrice !", _
48, "Donnée non numérique ou nulle"
End If
txtPasteData.Visible = False
End Sub

Private Sub cmdNoTopMost_Click()
''' Bouton Mode Non Modal appuyé
'''------------------------
If MsgBox("La calculatrice est affichée en mode verrouillé et vous devrez l'éteindre pour intervenir " & _
"sur la fenêtre en arrière-plan...", 49, "Mode d´affichage") = 1 Then
cmdTopMost.Visible = True
Me.Modal = True
cmdNoTopMost.Visible = False
ledTopMost.BackColor = RGB(255, 0, 0)
End If
End Sub

Private Sub cmdTopMost_Click()
''' Bouton Mode Modal appuyé
'''------------------------
If MsgBox("La calculatrice n´est plus en mode exclusif de fenêtre et vous pouvez intervenir " & _
"sur la fenêtre en arrière-plan...", 65, "Mode d´affichage") = 1 Then
cmdNoTopMost.Visible = True
Me.Modal = False
cmdTopMost.Visible = False
ledTopMost.BackColor = RGB(0, 255, 0)
End If
End Sub

Private Sub CopyResultToClipboard()
''' Procédure de gestion du presse-papier
'''----------------------------------------
m_vntTotalDisplayed = Val(Me!txtLCDDisplayEUR)

If m_vntTotalDisplayed = 0 Then GoTo L_ExCopyFail

DoCmd.GoToControl "txtLCDDisplayEUR"
m_vntFinalResult = ConvertToDouble(Me!txtLCDDisplayEUR)
txtHiddenFinalResult.Visible = True
Me!txtHiddenFinalResult = m_vntFinalResult
txtHiddenFinalResult.SetFocus
txtHiddenFinalResult.SelStart = 0
txtHiddenFinalResult.SelLength = Len(Me!txtHiddenFinalResult)
On Error GoTo L_ErrCopyFail
DoCmd.RunCommand acCmdCopy
btnOnOff.SetFocus
txtHiddenFinalResult.Visible = False

L_ExCopyFail:
Exit Sub
L_ErrCopyFail:
MsgBox "Désolé, la copie a échoué...", 48, "Copie"
Resume L_ExCopyFail
End Sub

Private Function GetSystemDecimalSeparator() As String
''' Fonction retournant le séparateur du système
'''---------------------------------------------
Const HKEY_CPANEL_INTLKEYS As String = "Control Panel\International"
Dim strDecimal As String

strDecimal = fRegistryGetKeyValue(rootHKeyCurrentUser, HKEY_CPANEL_INTLKEYS, "sDecimal")
If VarType(strDecimal) = vbError Then
Exit Function
End If
GetSystemDecimalSeparator = strDecimal
End Function

V-A-2 - Le code du Module basRegistry

Code du Module d´accès au Registre de Windows

''' ************************************************************************************
'''     PROJET        :   Calculator for MS Access Applications
'''     MODULE        :   basRegistry
'''     AUTEUR        :   Jean-Philippe AMBROSINO
'''     CONTACT       :   http://cerbermail.com/?wDzGFhHk1g
'''
'''     PUBLIÉ SUR    :   http://access.developpez.com/
'''
''' ************************************************************************************
Option Compare Database
Option Explicit

Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal lngHKey As Long) _
As Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" _
(ByVal lngHKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, _
ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegQueryValueExString Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal lngHKey As Long, ByVal lpValueName As String, ByVal _
lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) _
As Long
Private Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal lngHKey As Long, ByVal lpValueName As String, ByVal _
lpReserved As Long, lpType As Long, lpData As Long, lpcbData As Long) As Long
Private Declare Function RegQueryValueExBinary Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal lngHKey As Long, ByVal lpValueName As String, ByVal _
lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As _
Long
Private Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal lngHKey As Long, ByVal lpValueName As String, ByVal _
lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As _
Long

Public Enum EnumRegistryRootKeys
rootHKeyClassesRoot = &H80000000
rootHKeyCurrentUser = &H80000001
rootHKeyLocalMachine = &H80000002
rootHKeyUsers = &H80000003
End Enum

Public Enum EnumRegistryValueType
RRKREGSZ = 1
RRKREGBINARY = 3
RRKREGDWORD = 4
End Enum

Public Const HKEYLOCALMACHINE As String = "HKEY_LOCAL_MACHINE"
Public Const HKEYCURRENTUSER As String = "HKEY_CURRENT_USER"

Private Const mcregOptionNonVolatile = 0

Private Const MCREGERRORNONE = 0
Private Const MCREGKEYALLACCESS = &H3F
Private Const MCREGKEYQUERYVALUE = &H1

Public Function fRegistryGetKeyValue(ByVal eRootKey As EnumRegistryRootKeys, ByVal strKeyName As String, _
ByVal strValueName As String) As Variant
''' Fonction permettant la lecture d'une clé du registre
'''----------------------------------------------------
Dim lngRetVal As Long
Dim lngHKey As Long
Dim varValue As Variant
Dim strValueData As String
Dim abytValueData() As Byte
Dim lngValueData As Long
Dim lngValueType As Long
Dim lngDataSize As Long

On Error GoTo L_ErrRegistryOperation
varValue = Empty
lngRetVal = RegOpenKeyEx(eRootKey, strKeyName, 0&, MCREGKEYQUERYVALUE, lngHKey)
If MCREGERRORNONE = lngRetVal Then
lngRetVal = RegQueryValueExNULL(lngHKey, strValueName, 0&, lngValueType, 0&, lngDataSize)
If lngRetVal = MCREGERRORNONE Then
Select Case lngValueType
Case RRKREGSZ:
If lngDataSize > 0 Then
strValueData = String(lngDataSize, 0)
lngRetVal = RegQueryValueExString(lngHKey, strValueName, 0&, lngValueType, _
strValueData, lngDataSize)
If InStr(strValueData, vbNullChar) > 0 Then
strValueData = Mid$(strValueData, 1, InStr(strValueData, vbNullChar) - 1)
End If
End If
If MCREGERRORNONE = lngRetVal Then
varValue = Left$(strValueData, lngDataSize)
Else
varValue = Empty
End If
Case RRKREGDWORD:
lngRetVal = RegQueryValueExLong(lngHKey, strValueName, 0&, _
lngValueType, lngValueData, lngDataSize)
If MCREGERRORNONE = lngRetVal Then
varValue = lngValueData
End If
Case RRKREGBINARY
If lngDataSize > 0 Then
ReDim abytValueData(lngDataSize) As Byte
lngRetVal = RegQueryValueExBinary(lngHKey, strValueName, 0&, _
lngValueType, VarPtr(abytValueData(0)), lngDataSize)
End If
If MCREGERRORNONE = lngRetVal Then
varValue = abytValueData
Else
varValue = Empty
End If

Case Else
lngRetVal = -1
End Select

End If
RegCloseKey (lngHKey)
End If
fRegistryGetKeyValue = varValue

L_ExRegistryOperation:
Erase abytValueData
Exit Function
L_ErrRegistryOperation:
MsgBox "Error: " & Err.Number & ". " & Err.Description, , _
"fRegistryGetKeyValue"
Resume L_ExRegistryOperation
End Function

VI - Comment cela fonctionne-t-il ?

Le fonctionnement global est relativement simple : le formulaire intercepte les séquences de touche par l'événement Form_KeyDown et appelle la procédure associée selon le KeyCode correspondant.

Entrée de chiffres

Quelle que soit la valeur de KeyCode s'il s'agit d'un chiffre, la variable m_strLastFlagEntry prend la valeur appropriée et la fonction FlagActionButtons() est appelée. C'est elle qui régit l'affichage de ce qui est frappé ou cliqué et contrôle que ces séquences ne dépassent pas 13, nombre maximum de chiffres affichables.

Choix d'un opérateur

Quelle que soit la valeur de KeyCode s'il s'agit d'un opérateur, la variable m_strLastFlagEntry prend la valeur appropriée et la fonction FunctionOperator() est appelée. C'est elle qui régit le calcul de ce qui est demandé et contrôle l'erreur potentielle de la division par zéro puis met à jour l'affichage à partir du moment où le paramètre Operator de la fonction est égal à « = ».

Appelle des fonctions spéciales

Quelle que soit la valeur de KeyCode s'il s'agit d'une fonction mathématique spéciale, la variable m_strLastFlagEntry prend la valeur appropriée et chacun des boutons exécute le calcul selon que ce soit :

- une racine carrée : fonction SQR(valeur)
- l'inverse 1/x : opération 1 / valeur
- un pourcentage : opération valeur / 100
- une élévation X² : opération valeur * valeur

Appelle des fonctions de mémoire

Ici, une variable de module nommée « m_dblBufferMemory » sert de buffer pour stocker en plus ou en moins la valeur du résultat courant.

Appelle de fonction de Copier/Coller et de mode d'affichage

=> Copier : cette action appelle la fonction CopyResultToClipboard afin de stocker le résultat dans le presse-papier.

=> Coller : cette action appelle la fonction Application.RunCommand acCmdPaste afin de coller le résultat dans la zone de texte txtLCDDisplayEUR et appelle la fonction ConvertToFRF pour convertir instantanément la valeur en francs.

=> Mode : cette action change la propriété Modal à True ou à False selon le choix et change la visibilité du bouton ainsi que la couleur du rectangle selon le cas.

Les autres opérations

- L'extinction de la calculatrice ferme le formulaire et affiche un message pour conserver le résultat dans le presse-papier.

- L'utilisation de la touche C vide le contenu de la variable m_dblEuroValue et met les afficheurs à 0.

- Pour chacun des boutons, la fonction KeepFocus est appelée de manière à laisser le focus sur le bouton lors de l'utilisation du clavier pour simuler l'usage de la souris.

VII - Comment l'utiliser ?

Bien une fois que vous avez terminé la conception et testé en mode formulaire que tout fonctionnait correctement, vous pouvez ouvrir la calculatrice depuis un autre formulaire avec la méthode :

Ouvrir un formulaire

Private Sub cmdShowCalculator()
DoCmd.OpenForm "", acNormal, , , , acDialog
End Sub

VII-A - Elle est ouverte, mais je ne peux pas la déplacer !!!

Si effectivement vous avez, comme je l'ai stipulé, défini la propriété Fen indépendante à Oui, vous n'avez alors plus de barre de titre ; de ce fait, il est impossible de déplacer le formulaire.
La solution consiste alors à ajouter du code sur les événements Mouse_Move des rectangles de la calculatrice

Pour ce faire, vous devez ajouter un Module que vous nommez basAPI par exemple dans lequel vous copiez le code suivant :

Déclaration des API dans un module

Public Declare Function ReleaseCapture Lib "user32" () As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Const WM_NCLBUTTONDOWN = &HA1
Public Const HTCAPTION = 2

Il vous reste alors à gérer les événements pour chacun des rectangles comme suit :

Code du déplacement de la calculatrice

Private Sub imgAppButtons_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
MoveMyCalculator Button
End Sub

Private Sub shpCalc1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
MoveMyCalculator Button
End Sub

Private Sub shpCalc2_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
MoveMyCalculator Button
End Sub

Private Sub MoveMyCalculator(Button As Integer)
If Button = 1 Then
ReleaseCapture
SendMessage Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&
End If
End Sub

L'événement Mouse_Move exploite quatre paramètres :

- Button => identifie quel bouton (gauche ou droite) est appuyé ;

- Shift => identifie quelle touche du clavier parmi les touches Ctrl, Alt, Maj ;

- X => identifie la position horizontale du pointeur ;

- Y => identifie la position verticale du pointeur.

Dans la procédure MoveMyCalculator, on identifie le bouton et si c'est bien le bouton gauche qui est appuyé (1) alors les appels des fonctions ReleaseCapture et de SendMessage sont lancés et permettent d'effectuer le déplacement de la fenêtre.

VIII - Conclusion

Ce petit projet reste intéressant pour les développeurs qui souhaitent mettre à la disposition des utilisateurs de leurs applications une calculatrice personnalisée.

Les avantages ont été évoqués en début de document et personnellement, je préfère offrir une calculette de ce type pour mes applications plutôt que mettre un exécutable qui ouvrirait de façon unique et au premier plan la calculatrice de Windows (la calculatrice de Windows est malheureusement multiinstance).

Je vous laisse donc créer votre calculette personnalisée avec pourquoi pas, d'autres fonctions spécifiques associées à d'autres boutons. Les possibilités sont vastes, ce tutoriel étant en fait une petite base de départ.
N'hésitez pas à me contacter si vous rencontrez des difficultés.