Comment faire défiler les fiches en maintenant le bouton gauche de la souris appuyé

Jean-Philippe AMBROSINO

Ce document a pour but de vous montrer comment faire défiler les fiches en maintenant le bouton gauche de la souris appuyé. Vous devez maîtriser la conception des formulaires, connaître le langage Visual Basic for Application pour mettre en œuvre cet exemple et savoir manipuler plus particulièrement les RecordSets.

Commentez

- Titre : Comment faire défiler les fiches en maintenant le bouton gauche de la souris appuyé

- Auteur : Jean-Philippe AMBROSINO

- Parution : 23 août 2005

- Mise à jour : 23 août 2005

- Licence : Ce document est issu de https://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 formulaire exemple

- II-A. Le formulaire et ses boutons

- II-B. Les contrôles du formulaire

- II-C. Création des boutons de défilement

- II-D. Code nécessaire au démarrage du formulaire

- III. Code événement des boutons de défilement continu

- III-A. Le code des boutons

- IV. Conclusion

I - Avant-propos

Ce document a pour but de vous montrer comment faire défiler les fiches en maintenant le bouton gauche de la souris appuyé.
En effet, un bouton Suivant ou Précédent fait défiler les fiches une à une, mais le maintien appuyé de la souris sur un de ces boutons n'a aucun autre effet.
Grâce à ce tutoriel, vous serez à même de mettre en œuvre une routine idoine.

I-A - Remerciements

Je tiens à remercier tout particulièrement 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 formulaire exemple

Dans un formulaire dédié à la consultation (et l'éventuelle mise à jour) des fiches, un jeu de boutons de défilement des enregistrements est souvent nécessaire.
Toutefois, un utilisateur peut très bien être amené à vouloir disposer d'un défilement rapide des enregistrements pour pouvoir accéder à telle ou telle fiche sans passer par un filtre.
Les explications qui vont suivre sont à même de vous montrer qu'il est possible faire défiler les fiches en mode rapide (éventuellement paramétrable) grâce à l'adjonction de deux boutons complémentaires de défilement continu.

II-A - Le formulaire et ses boutons

Vous pouvez constater que ce formulaire est volontairement dépourvu du sélecteur et du diviseur d'enregistrements et de tout autre bouton lié à la fenêtre, rendant celle-ci totalement indépendante.
J'ai également pour les mêmes raisons d'esthétique d'une part et pour l'objectif de ce tutoriel en parallèle, supprimé les boutons de déplacement.

Le formulaire en mode formulaire

II-B - Les contrôles du formulaire

Lorsque l'on passe en Mode Création, vous pouvez visualiser l'ensemble des contrôles utilisés dans le formulaire. Ceux qui nous intéressent sont les contrôles « Boutons de commande » pourvus d'une flèche haut et bas de couleur bleu foncé, intercalées entre les boutons de déplacements classiques.
Pour rappel, ces boutons de déplacement utilisent une routine issue de la méthode DoCmd.GotoRecord avec les constantes acFirst, acPrevious, acNext et acLast. Pour ce tutoriel, je vais vous proposer d'utiliser également ces méthodes, mais celles-ci seront greffées de quelques lignes de code complémentaires indispensables.

Le formulaire en mode création (Design)

II-C - Création des boutons de défilement

Pour mettre en application ce tutoriel, vous avez besoin de deux boutons que vous nommerez avec un nom circonstanciel respectif.
Dans notre exemple, ces boutons se nomment cmdPreviousMore et cmdNextMore.
Nous allons aborder au pas à pas chaque étape pour aboutir au résultat final.

Détail des éléments utilisés

Vous devez donc dessiner un bouton (sans demander à Saint Exupéry) et lui affecter une image que vous pouvez piocher dans la bibliothèque d'images ou bien une icône que vous aurez dessinée ou récupérée sur une source externe.
Pour ce faire, utilisez l'outil « Bouton » disponible dans la boîte à outils et dessinez une forme rectangulaire adaptée à votre formulaire.
Répétez l'opération pour un second bouton ou bien dupliquez celui-ci (ce qui vous assure d'avoir deux boutons identiques) puis nommez-les.

Création des boutons

Une fois les boutons nommés et alignés, vous devez leur affecter un code événement.
Mais, le code événement nécessaire au fonctionnement du défilement des fiches requiert l'initialisation de variables au moment du chargement du formulaire.
En effet, il est impératif de définir la vitesse du défilement après avoir également pris connaissance de l'état des boutons de la souris grâce aux fonctions API vues ci-après.

II-D - Code nécessaire au démarrage du formulaire

Vous écrirez ou recopierez donc dans la section Form_Load de votre formulaire le code suivant :

Module du formulaire contenant les boutons

Private m_dblSpinSpeed As Double
Private m_intMouseButton As Integer

Private Sub Form_Load()
If GetSystemMetrics(SM_SWAPBUTTON) = 1 Then
m_intMouseButton = VK_RBUTTON
Else
m_intMouseButton = VK_LBUTTON
End If
m_dblSpinSpeed = 0.059
End Sub

Vous écrirez ou recopierez ensuite dans un module nommé « basDeclarations » s'il n'en existe pas ou bien dans un module où vous avez déjà des API's déclarées, le code suivant:

Module de déclaration des API et des constantes

Option Explicit
Public Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Public Const VK_LBUTTON As Long = &H1
Public Const VK_RBUTTON As Long = &H2
Public Const SM_SWAPBUTTON% = 23

Détail des variables utilisées

- La variable de module « m_dblSpinSpeed » est déclarée en entête de module. Elle est initialisée durant l'événement Form_Load et définie la vitesse de défilement des fiches.

- Les API GetSystemMetrics et GetAsyncKeyState sont déclarées en Private dans le module lui-même ou en Public si vous souhaitez exploiter cette fonctionnalité dans plusieurs formulaires différents. Elles sont dédiées respectivement à connaître périodiquement l'état des boutons de la souris pour la première et de renvoyer la valeur correspondante à l'état de permutation de ces boutons pour la seconde.

- Les constantes SM_SWAPBUTTON, VK_RBUTTON et VK_LBUTTON sont également déclarées avec les mêmes conditions.

- La variable de module m_intMouseButton est déclarée en entête de module. Elle est initialisée par l'API précitée et définit le bouton de la souris utilisé.

III - Code événement des boutons de défilement continu

Pour faire défiler les fiches une à une en maintenant le bouton de la souris appuyé, il est nécessaire d'affecter aux boutons qui ont été ajoutés au formulaire un code événement.
L'Assistant Bouton propose pour parcourir les enregistrements avec un défilement manuel fiche à fiche, des boutons prédéfinis associés au code événement « Click ».
Pour le cas du défilement continu, c'est différent et vous exploiterez les événements MouseDown et MouseUp sans tenir compte des arguments, car ils ne sont pas utilisés dans les exemples.

Si pour une raison particulière, vous aviez besoin de forcer l'utilisateur à complémenter l'appui d'une touche de clavier en plus de celui de la souris pour bénéficier d'un défilement continu, vous devrez exploiter le paramètre « Shift » et éventuellement, le paramètre « Button ».

En effet, vous pourriez très bien ne pas vouloir poser deux autres boutons supplémentaires qui pourraient prêter à confusion et faire en sorte que les boutons de défilement classiques se substituent à ceux offrant un défilement continu si l'utilisateur appuie par exemple sur la touche « Ctrl » simultanément.

Je n'aborderai pas cette partie conditionnelle de code ici, car elle sort du contexte.

III-A - Le code des boutons

Vous devez donc recopier le code ci-dessous pour chaque bouton.
- Pour le bouton devant faire un défilement continu remontant, copier le code exemple cmdPreviousMore_MouseDown.
- Pour le bouton devant faire un défilement continu descendant, copier le code exemple cmdNextMore_MouseDown.

Code du bouton de défilement continu Précédent

Private Sub cmdPreviousMore_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Const MESSAGE_INFO As String = "Il n'y a pas de fiche précédente !"
Const MESSAGE_TITLE As String = "Parcours des fiches"

Dim sgnTickCount1 As Single
Dim sgnTickCount2 As Single
Dim sgnTickCount3 As Single
Dim intKeyState As Integer

On Error Resume Next
If Button = 1 Then
sgnTickCount1 = Timer
Do Until sgnTickCount2 > sgnTickCount1 + m_dblSpinSpeed
sgnTickCount2 = Timer
DoEvents
intKeyState = GetAsyncKeyState(m_intMouseButton)
If intKeyState = 0 Then Exit Sub
Loop
On Error GoTo Err_cmdPreviousMore
DoCmd.GoToRecord , , acPrevious
L_GotoPrevious:
Do Until sgnTickCount3 > sgnTickCount2 + m_dblSpinSpeed
sgnTickCount3 = Timer
DoEvents
Loop
intKeyState = GetAsyncKeyState(m_intMouseButton)
If intKeyState <> 0 Then
On Error GoTo Err_cmdPreviousMore
DoCmd.GoToRecord , , acPrevious
sgnTickCount2 = Timer
DoEvents
GoTo L_GotoPrevious
End If
End If
Exit_cmdPreviousMore:
Exit Sub
Err_cmdPreviousMore:
If Err <> 94 Then
MsgBox MESSAGE_INFO, 64, MESSAGE_TITLE
End If
Resume Exit_cmdPreviousMore
End Sub

Code du bouton de défilement continu Suivant

Private Sub cmdNextMore_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Const MESSAGE_INFO As String = "Il n'y a pas de fiche suivante !"
Const MESSAGE_TITLE As String = "Parcours des fiches"

Dim sgnTickCount1 As Single
Dim sgnTickCount2 As Single
Dim sgnTickCount3 As Single
Dim intKeyState As Integer

On Error Resume Next
If Button = 1 Then
sgnTickCount1 = Timer
Do Until sgnTickCount2 > sgnTickCount1 + m_dblSpinSpeed
sgnTickCount2 = Timer
DoEvents
intKeyState = GetAsyncKeyState(m_intMouseButton)
If intKeyState = 0 Then Exit Sub
Loop
On Error GoTo Err_cmdNextMore
DoCmd.GoToRecord , , acNext
L_GotoNext:
Do Until sgnTickCount3 > sgnTickCount2 + m_dblSpinSpeed
sgnTickCount3 = Timer
DoEvents
Loop
intKeyState = GetAsyncKeyState(m_intMouseButton)
If intKeyState <> 0 Then
On Error GoTo Err_cmdNextMore
DoCmd.GoToRecord , , acNext
sgnTickCount2 = Timer
DoEvents
GoTo L_GotoNext
End If
End If
Exit_cmdNextMore:
Exit Sub
Err_cmdNextMore:
If Err <> 94 Then
MsgBox MESSAGE_INFO, 64, MESSAGE_TITLE
End If
Resume Exit_cmdNextMore
End Sub

Comment ça marche ?

Les procédures de défilement continu exploitent la fonction Timer.

Cette fonction renvoie une valeur de type Single qui représente le nombre de secondes qui se sont écoulées depuis minuit dans la session Windows en cours.
L'intérêt d'user de cette fonction dans la boucle Do/Loop permet de déterminer si le nombre de secondes écoulées à partir du moment où l'utilisateur a pressé le bouton gauche de sa souris est égal à la somme des secondes additionnée à l'intervalle de temps défini par la variable m_dblSpinSpeed. Cette dernière détermine la vitesse du défilement.
Ainsi, tant que cette valeur n'est pas atteinte, on provoque un DoEvents qui sert à donner le contrôle à d'autres processus durant cet intervalle.
Bien entendu, cela est totalement transparent puisque ces intervalles se calculent en millisecondes.
Enfin, dès que la valeur attendue est atteinte, on appelle alors le DoCmd.GoToRecord pour afficher l'enregistrement Suivant ou Précédent, selon le cas.

Pour mieux comprendre l'usage de la fonction Timer, voici un petit bout de code que vous pouvez tester ;
Dans cet exemple, la fonction Timer va permettre de provoquer une pause de 8 secondes et durant cette pause, d'autres processus vont être exécutés grâce à la fonction DoEvents.

Exemple

Exemple d'usage de la fonction Timer

Sub TestTimer()
Dim sgnDureePause As Single
Dim sgnDepart As Single
Dim sgnFin As Single
Dim sgnTempsTotal As Single

'Définition de la durée.
sgnDureePause = 8
If MsgBox("Voulez-vous marquer une pause de " & Trim(Str(sgnDureePause)) & " secondes", 36, "Marquer une pause") = 6 Then
'Définition l'heure de départ.
sgnDepart = Timer
Do While Timer < sgnDepart + sgnDureePause
'Boucle de comparaison qui donne le contrôle à d'autres processus tant que la condition n'est pas vérifiée.
DoEvents
Loop
'Définition l'heure de fin.
sgnFin = Timer
'On calcule alors la différence de temps écoulé.
sgnTempsTotal = sgnFin - sgnDepart
MsgBox "La pause de " & sgnTempsTotal & " secondes est maintenant terminée...", , "Fin de pause"
End If
End Sub

C'est terminé…
Cela reste relativement simple à mettre en place compte tenu que le code est axé principalement sur les boutons.
Il vous suffit donc de passer en Mode formulaire puis de tester chacun des boutons.
L'implémentation des gestions d'erreurs permet d'afficher un message idoine dès que le premier ou le dernier enregistrement est atteint ; bien entendu, vous pouvez personnaliser ces messages qui sont stockés dans des constantes.

IV - Conclusion

Ce tutoriel peut s'avérer utile pour les développeurs exigeants qui souhaitent fournir des formulaires avec des fonctionnalités évoluées. J'en ai fait les frais pour certains projets et je partage aujourd'hui pour vous ce petit plus… Je précise que ce qui a motivé la rédaction de ce tutoriel est une question posée sur le Forum.
Le côté intéressant de cette fonctionnalité est que vous pouvez l'exploiter pour tout autre type d'utilisation par exemple le choix d'une valeur dans un champ pour un jeu d'enregistrements donné…
À vous de vous amuser avec, les possibilités sont grandes.