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 :
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 :
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.
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 : |
Mode Modal : il est nécessaire de fermer la calculatrice pour avoir la main sur le formulaire appelant : |
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 :
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
''' ************************************************************************************
''' 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
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
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.
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.
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.
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.
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.
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.
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.
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▲
''' ************************************************************************************
''' 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 :
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 :
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 :
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.