Comment positionner un formulaire ouvert depuis un autre, à droite de l'écran

Jean-Philippe AMBROSINO

Ce document a pour but de vous montrer comment faire pour positionner un formulaire ouvert depuis un formulaire principal à droite de l'écran avec une position verticale prédéfinie.
Vous devez maîtriser la conception des formulaires, connaitre le langage Visual Basic for Application pour mettre en œuvre cet exemple et savoir manipuler plus particulièrement les API Windows.

Commentez ♪

- Titre : Comment positionner un formulaire ouvert depuis un autre, à droite de l'écran

- Auteur : Jean-Philippe AMBROSINO

- Parution : 1 octobre 2005

- Mise à jour : 1 octobre 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 dupliqué et son bouton

- II-B. Les propriétés à redéfinir

- III. Conception du formulaire principal

- III-A. Conception du formulaire principal

- III-A-1. Propriétés des contrôles du formulaire principal

- III-A-2. Code des contrôles du formulaire principal

- III-A-2-a. Description du code du formulaire principal

- III-B. Le formulaire principal en mode formulaire

- IV. Le module

- IV-A. Code du module

- IV-A-1. Description du code du module

- IV-B. Mise en œuvre de l'utilisation

- V. Conclusion

- VI. Vocabulaire

I - Avant-propos

Ce document a pour but de vous montrer comment il est possible de positionner un formulaire à l'extrême droite de l'écran.
En effet, lorsque vous ouvrez un formulaire Access, celui-ci se positionne là où il à été positionné lors de la dernière utilisation, cette dernière étant enregistrée dans les propriétés de celui-ci.
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

J'ai utilisé la base de données « Les Comptoirs » pour vous servir d'exemple.
Pour ce faire, vous devez dupliquer le formulaire nommé « Démarrage » et vous le renommerez pour la circonstance frmStartup.
Vous aurez pris soin de supprimer les éléments non utilisés dans ce dernier comme le montre l'illustration ci-dessous.

II-A - Le formulaire dupliqué et son bouton

Vous noterez qu'il n'y a aucune procédure Visual Basic dans le code de ce formulaire.
Seul le bouton OK exploite une macro =FermeFormulaire()
Son rôle ne présente aucun intérêt pour ce tutoriel puisque vous pouvez fermer un formulaire Access aussi bien avec du code qu'avec une macro, ma préférence étant bien entendu axée sur une procédure Visual Basic.

Le formulaire en mode création

Le formulaire en mode formulaire

II-B - Les propriétés à redéfinir

Pour vérifier que votre formulaire est opérationnel, il vous faut supprimer un certain nombre de propriétés prédéfinies sur celui-ci.
Vous ouvrirez donc les propriétés du formulaire et les définirez comme suit :

- Auto centrer : ……………………….….. Non

- Fenêtre indépendante : ……………. Oui

- Fenêtre modale : ………………………. Oui

Les propriétés du formulaire à ouvrir

C'est terminé pour ce formulaire, vous pouvez l'enregistrer et le fermer.

III - Conception du formulaire principal

Il s'agit du formulaire que vous avez certainement déjà conçu dans votre application.
Du fait que je ne sais pas substituer votre formulaire à celui que nous avons à concevoir, je vais vous proposer de créer celui-ci.
Il vous suffira par la suite d'adapter selon vos besoins en respectant les appels de code.

III-A - Conception du formulaire principal

Pour concevoir le formulaire manuellement, depuis la fenêtre Base de données, choisissez Nouveau
L'image ci-après apparaît et vous sélectionnez alors Mode création

Vous n'avez pas de table ni de requête à affecter comme source du formulaire pour cet exemple.

Cliquez sur OK

Étape 1
Le formulaire se présente vide avec seulement la section Détail visible.

Étape 2
Vous devez poser sur ce formulaire les contrôles nécessaires comme suit.

Un groupe d'option
Vous poserez d'abord un groupe d'options comme illustré ci-après (que vous pouvez concevoir avec l'Assistant Contrôle )

Les options, leurs étiquettes et leurs valeurs respectives du groupe d'options sont les suivantes

- En &haut à droite …………………………… 1

- Au &milieu à droite ………………………… 2

- En &bas à droite ……………………………. 3

Ne mettez pas de valeur par défaut sur ce groupe d'options.
Vous lui appliquerez un look circonstanciel et le nommerez fraTopPosition.

Une case à cocher
Vous poserez ensuite une case à cocher comme illustré ci-après que vous nommerez chkSetFocusToForm et dont l'étiquette s'intitulera « Donner le &focus au formulaire ».

Un bouton d'ouverture
Vous poserez enfin un bouton de commande comme illustré ci-après que vous nommerez cmdOpenForm et dont l'étiquette s'intitulera « &Ouvrir Le formulaire ».

Notez le symbole & précédant chaque intitulé d'étiquette et servant à définir le raccourci clavier.

Le formulaire principal en mode création

III-A-1 - Propriétés des contrôles du formulaire principal

Les contrôles que vous avez posés ne nécessitent pas de grosses modifications en ce qui concerne les propriétés.
Vous avez déjà défini celles du groupe d'options et il vous reste à définir la propriété Enabled (Activé) du bouton de commande à False (Non)

Il sera toutefois nécessaire de définir les propriétés d'événement dans le code, chose vue ci-après.

Elles se traduisent simplement de la façon suivante :

- - par l'événement Click (Sur clic) pour le bouton ;

- - par l'événement AfterUpdate (Après MAJ) pour le groupe d'options ;

- - par l'événement Load (Sur chargement) pour le formulaire lui-même.

III-A-2 - Code des contrôles du formulaire principal

En ce qui concerne le code Visual Basic de ce formulaire, il se traduit par ces quelques lignes :

Code du formulaire principal

Option Compare Database
Option Explicit
' Affichage du formulaire
Private Sub cmdOpenForm_Click()
DoCmd.OpenForm "frmStartup", acNormal, , , , acHidden
subMoveFormToRight "frmStartup", Me!fraTopPosition, Me!chkSetFocusToForm
fraTopPosition.SetFocus
cmdOpenForm.Enabled = False
End Sub
' Initialisation des contrôles
Private Sub Form_Load()
Me!fraTopPosition = 0
Me!chkSetFocusToForm = False
End Sub
' Événement du cadre d'options
Private Sub fraTopPosition_AfterUpdate()
cmdOpenForm.Enabled = True
End Sub

III-A-2-a - Description du code du formulaire principal

Le code du formulaire principal possède trois codes événements

- cmdOpenForm_Click qui a pour rôle de déclencher l'ouverture du formulaire en question (frmStartup). La méthode utilise la fonction DoCmd.OpenForm en spécifiant dans un premier temps que l'on veut ouvrir le formulaire en mode caché…

Pourquoi caché ? Tout simplement parce que l'on ne sait pas déterminer sa position à son ouverture considérant qu'un formulaire est flottant et que sa position est mémorisée dès qu'on le ferme si aucune propriété (AutoCentrer par exemple) ne contre celle-ci.
De ce fait, il ne faut pas que le formulaire soit visible.
Ensuite, la procédure publique subMoveFormToRight (vue ci-après) utilise respectivement trois arguments :

Enfin, la procédure redonne le focus au groupe d'options et désactive le bouton.

- fraTopPosition_AfterUpdate se contente de rendre activé le bouton « cmdOpenForm ».
La valeur de 1 à 3 qu'il renvoie est définie par les différentes valeurs des options et sera passée en paramètre dans la procédure subMoveFormToRight.

- Form_Load est écrit ainsi par prudence pour initialiser le contrôle CheckBox à False pour éviter qu'il soit Null et ainsi générer une erreur. Aussi, pour le cas où vous n'auriez pas prêté attention à la valeur par défaut du groupe d'options, cette valeur est affectée à zéro (aucune option cochée).

C'est terminé pour ce formulaire, il ne vous restera plus qu'à l'enregistrer et le fermer

III-B - Le formulaire principal en mode formulaire

Lorsque vous passez en mode formulaire, vous devez obtenir quelque chose comme ceci :

IV - Le module

Pour achever la conception de ce tutoriel, il vous faut insérer un module contenant le code principal de ce projet. Ce module que vous nommerez basMoveForm contiendra la routine publique qui sera chargée de placer le formulaire.

IV-A - Code du module

Le code du module se compose de Constantes, d'un Enum, de cinq déclarations d'API Windows.
La seule procédure publique subMoveFormToRight de ce module exploite tous ces éléments.

Code du module

Option Compare Database
Option Explicit

' Énumération des positions souhaitées
Public Enum eRightPosition
SetToTop = 1
SetToCenter = 2
SetToBottom = 3
End Enum

' Constantes de l'Api SetWindowPos()
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOACTIVATE = &H10
Private Const SWP_SHOWWINDOW = &H40
Private Const SWP_HIDEWINDOW = &H80
Private Const SWP_FOCUSWINDOW = 0

' Constantes des API GetSystemMetrics() et GetDeviceCaps()
Private Const SM_CXSCREEN = 0
Private Const SM_CYSCREEN = 1
Private Const HWND_DESKTOP As Long = 0
Private Const LOGPIXELSX As Long = 88
Private Const LOGPIXELSY As Long = 90

' Constantes des dimensions de marge et barre de titre de la fenêtre
Private Const SCREEN_MARGIN = 5
Private Const SCREEN_TITLEBAR = 30

'API Windows
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) _
As Long
Private Declare Sub SetWindowPos Lib "user32" (ByVal Hwnd As Long, ByVal _
hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long)
Private Declare Function GetDC Lib "user32" (ByVal Hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal Hwnd As Long, ByVal hdc _
As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal _
nIndex As Long) As Long

'
'*******************************************************************************
' Procédure : subMoveFormToRight
' Rôle: Permet de positionner un formulaire sur la partie droite de l'écran
' Paramètres:
'    - FormName : Nom du formulaire
'    - RightPosition : Valeur de la position de 1 à 3 fondée sur eRightPosition
'    - ActivateWindow : True ou False (True donne le focus à la fenêtre déplacée)
'*******************************************************************************
'
Public Sub subMoveFormToRight(ByVal FormName As String, Optional ByVal _
RightPosition As eRightPosition, Optional ByVal ActivateWindow As Boolean = False)

Dim sngScreenWitdh As Single
Dim sngScreenHeight As Single
Dim TwipsPerPixelX As Long
Dim TwipsPerPixelY As Long
Dim lngNewX As Long
Dim lngNewY As Long
Dim lngDC As Long

Dim lngHorizontalPosition As Long
Dim lngVerticalPosition As Long
Dim lngFormHwnd As Long
Dim lngFormWidth As Long
Dim lngFormHeight As Long

' Initialisation des coordonnées du formulaire et de son Handle
With Forms(FormName)
lngFormHwnd = .Hwnd
lngFormWidth = .InsideWidth
lngFormHeight = .InsideHeight
End With

' Calculs relatifs à l'écran
lngDC = GetDC(HWND_DESKTOP)
TwipsPerPixelX = 1440& / GetDeviceCaps(lngDC, LOGPIXELSX)
TwipsPerPixelY = 1440& / GetDeviceCaps(lngDC, LOGPIXELSY)
ReleaseDC HWND_DESKTOP, lngDC

lngHorizontalPosition = lngFormWidth \ TwipsPerPixelX
lngVerticalPosition = lngFormHeight \ TwipsPerPixelY

sngScreenWitdh = GetSystemMetrics(SM_CXSCREEN)
sngScreenHeight = GetSystemMetrics(SM_CYSCREEN)

lngNewX = (sngScreenWitdh - lngHorizontalPosition) - SCREEN_MARGIN
'Vérification de la position verticale choisie
Select Case RightPosition
Case SetToTop
lngNewY = 0
Case SetToBottom
lngNewY = (sngScreenHeight - lngVerticalPosition) - SCREEN_TITLEBAR
Case Else
lngNewY = ((sngScreenHeight - lngVerticalPosition) - SCREEN_MARGIN) \ 2
End Select

' Positionnement final du formulaire
SetWindowPos lngFormHwnd, HWND_TOPMOST, lngNewX, lngNewY, 0, 0, SWP_SHOWWINDOW _
Or SWP_NOSIZE Or IIf(ActivateWindow, SWP_FOCUSWINDOW, SWP_NOACTIVATE)

End Sub

IV-A-1 - Description du code du module

Le code de la procédure subMoveFormToRight

Dans un premier temps, le formulaire à positionner est déjà ouvert et caché. Du fait que son nom est passé en paramètre (ByVal FormName As String) cela permet d'obtenir les informations qui nous intéressent à son sujet à savoir :

- son Handle ;

- sa longueur (InsideWidth) ;

- sa hauteur (InsideHeight) ;

' Initialisation des coordonnées du formulaire et de son Handle
With Forms(FormName)
lngFormHwnd = .Hwnd
lngFormWidth = .InsideWidth
lngFormHeight = .InsideHeight
End With

À ce stade, le formulaire est toujours invisible.
Ensuite, par le biais de différentes API, on initialise des variables pour connaitre le nombre de twips par pixel. Ceci va servir à effectuer les différents calculs pour déterminer la taille de l'écran et ainsi, pouvoir déterminer les nouvelles valeurs de X et de Y du l'API SetWindowPos.

=> La variable lngNewX qui sert à déterminer de combien de pixels on va déplacer horizontalement le formulaire est maintenant initialisée.

Avec le bloc Select Case/End Select, on est à même de savoir quelle sera la position verticale de la fenêtre selon les trois choix établis par le groupe d'options vu ci-avant ; ces positions sont définies par l'Enum eRightPosition où chacun des éléments prend la valeur de 1 à 3 correspondant justement aux trois options du groupe d'options.

=> La variable lngNewY qui sert à déterminer de combien de pixels on va déplacer verticalement le formulaire est à son tour, initialisée.

On donne le focus à la fenêtre si la variable ActivateWindow est affectée à True.
Enfin, on rappelle l'API SetWindowPos() avec les nouvelles valeurs de X et de Y toujours avec les arguments nécessaires pour placer cette fois, le formulaire sur le bord droit de l'écran et selon le cas, en haut, au milieu ou en bas.

- La constante SCREEN_MARGIN est utilisée pour soustraire la valeur des X à concurrence de la largeur de la bordure d'une fenêtre.
- La constante SCREEN_TITLEBAR est utilisée pour soustraire la valeur des Y à concurrence de la hauteur de la barre de titre d'une fenêtre.

Bien entendu, vous pouvez modifier la valeur de SCREEN_MARGIN si vous souhaitez ne pas faire coller la fenêtre sur la bordure droite, mais un peu en retrait.

Attention

Les Enum ne sont pas exploitables dans la version 97 d'Access et antérieures. Aussi, il vous faudra remplacer ces valeurs par des constantes et adapter le code en conséquence.

C'est terminé
Il ne vous reste plus qu'à exécuter le tout en ouvrant le formulaire principal en mode formulaire.

Je vous recommande de compiler votre projet afin de vous assurer que vous n'avez pas fait d'erreur de syntaxe, synonyme de plantage et de dysfonctionnement.

Pour effectuer une compilation, dans l'éditeur Visual Basic, cliquez sur le Menu Débogage/Compiler Comptoir.

Bien entendu, le menu Compiler… sera suivi du nom de votre application.

IV-B - Mise en œuvre de l'utilisation

Le résultat est conséquent au choix que vous avez effectué :

V - Conclusion

Ce tutoriel peut s'avérer utile pour les développeurs qui souhaitent manipuler plus facilement l'ouverture des formulaires. J'en ai fait les frais pour certains projets et je partage aujourd'hui avec 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 par un utilisateur qui souhaitait justement ouvrir un formulaire à un endroit ciblé sur l'écran.

Ce tutoriel, plus théorique que pratique, permet de répondre à une telle demande à partir du moment où vous déterminez vous-même le niveau de tolérance de la valeur des constantes SCREEN_MARGIN et SCREEN_TITLEBAR… Vous prêterez en revanche attention à ce que les nouvelles valeurs attribuées rentrent dans une plage conforme.

VI - Vocabulaire

TWIPS
Abréviation de « twentieth of a point ». Unité de mesure de longueur utilisée dans la conception d'objets graphiques.
1 twip est égal à 1/20e de point, 1/1440e de pouce.

HANDLE
Valeur numérique identifiant un objet informatique (§ une fenêtre ou un fichier) et permettant donc sa « manipulation » ou sa gestion (to handle en anglais). L'abréviation de cette valeur est souvent nommée HWnd.