Centrer un userform sur un écran

Bonjour,
Nous avons tous des pc avec 2 écran et dans une macro, j’ai un userform qui à la fâcheuse tendance a s’ouvrir sur le mauvais écran (Solidworks sur écran de gauche par ex et userform sur l’écran de droite)
Sur Excel j’avais ce code qui fonctionne très bien:

Private Sub UserForm_Initialize()
    '-------------------------------------------------------- Positionnement UserForm
    Me.StartUpPosition = 0                                                  'Déclarer position MANUAL
    Me.Left = Application.Left + Application.Width / 2 - Me.Width / 2
    Me.Top = Application.Top + Application.Height / 2 - Me.Height / 2
End Sub

Mais ce code provoque une erreur 438
Le seul sujet trouvé s’approchant de ça est celui ci et la page de la réponse n’est plus accessible. (Prb Userform - #7 par jfaradon)
Si quelqu’un sait comment corriger ce problème.

1 « J'aime »

bonjour

StartUpPosition tu la modifie directement dans la fenêtre des propriétés, pas besoin de le faire en VBA

exemple

UserForm1.Move 100, 100 'Uniquement pour déplacer à gauche et en haut.
UserForm1.left = 100 'pour déplacer latéralement
UserForm1.Top = 100 ' pour déplacer verticalement
UserForm1.Move 100, 100, 250, 190 'pour tout modifier


Private Sub UserForm_Initialize()
UserForm1.Move 100, 100, 250, 190
End Sub
2 « J'aime »

Oui le .Move c’est ce que j’ai actuellement, mais pose problème avec 2 écrans.
Code actuelle:

Private Sub UserForm_Initialize()
    With Me
        .StartUpPosition = 3
        .Move 100, 100
    End With
End Sub

Mais le soucis c’est que si la fenêtre solidworks est sur l’écran de gauche (2 écrans), pas de soucis le userform est bien au dessus de SW.
Mais si l’utilisateur à mis Solidworks sur son écran de droite le userform se retrouve sur l’écran de gauche, à l’opposé de SW.
C’est pourquoi je cherche une alternative comme sous Excel (code du 1er message, mais non fonctionnel sous SW.

je vois 1 problème
l’USF avec startuposition sur 1-centerowner devrait mettre l’usf au centre de l’application qui l’a lancé ce qui n’est pas le cas

« application.quelque chose » ne fonctionne pas

voir ce sujet ou j’ai dû remplacer application, je pense que c’est le même principe, pour le moment je n’ai pas trouvé

2 « J'aime »

Bonjour @sbadenis
Essayez ceci

Public swapp as sldworks.Sldworks

Et

Private Sub UserForm_Initialize()
    '-------------------------------------------------------- Positionnement UserForm
    Me.StartUpPosition = 0                                                  'Déclarer position MANUAL
    Me.Left = swapp.Frameleft + swapp.Framewidth / 2 - Me.Width / 2
    Me.Top = swapp.Frametop + swapp.Frameheight / 2 - Me.Height / 2
End Sub
2 « J'aime »

Bonjour,
La réponse de @Lynkoa15 semble bonne par contre j’ai testé et les valeurs renvoyées sont assez étranges.
Il me sort les valeurs suivantes pour un double écran paramétré sur celui où est ouvert SW en 1680x1050:
Left = 897
Width = 1024
Top = 0
Height = 768
Ce qui a pour résultat de positionner le UserForm au milieu des deux écrans.
Pour le conserver sur l’écran de gauche (pour moi SW est à gauche sur l’écran principal) j’ai retiré Swapp.FramLeft du calcul pour Me.Left.
Ca m’a positionné le UserForm sur l’écran de gauche, pas vraiment centré dans la fenêtre dans la largeur, la hauteur quant à elle est bonne même si le height n’a rien à voir avec ma résolution d’affichage.

1 « J'aime »

Cyrille, c’est étrange, j’ai pas un double écran et j’ai pas testé, mais si ça permet de faire basculer la fenêtre vers le deuxième écran, une analyse de l’écart avec les dimensions de ce dernier doit être possible, peut-être une difereance entre la résolution écran et résolution affichage windows

1 « J'aime »

Je n’ai pas la même résolution entre l’écran de gauche et l’écran de droite. Ca vient peut-être de ça, je referai un test avec un seul écran pour voir.

1 « J'aime »

Pour moi pas tout à fait centré sur l’écran de gauche et sur l’écran de droite complètement décentré.
En ajoutant des parenthèse légèrement décentré sur les 2 écrans (même taille), je m’approche de la vérité, mais il y a tout de même un comportement un peu bizarre et différent de la solution sous excel.

    Me.Left = ((swapp.FrameLeft + swapp.FrameWidth) / 2) - (Me.Width / 2)
    Me.Top = ((swapp.FrameTop + swapp.FrameHeight) / 2) - (Me.Height / 2)

Pas le temps de creuser les 2-3 prochains jours, le boulot me rattrape.
Je reviens vers vous dès que possible.
En tout cas @Lynkoa15 , ta solution est la plus proche et fonctionnelle à ce jour!

Bonjour @sbadenis ,

Effectivement, Windows gère les deux écrans comme un seul en cumulant les pixels en largeur.
C’est confirmé par la macro jointe, piochée par morceaux sur le net, et adaptée pour renvoyer les dimensions des deux écrans et la position de la fenêtre de SolidWorks.

L’écart observé en utilisant la proposition de @Lynkoa15 me semble lié à une confusion d’unités pour les coordonnées écran :

  • les dimensions et la position de la fiche UserForm (.Left, .Top, .Widt et .Height) sont définies par VBA en points écran.
  • les dimensions et la position de la fenêtre SolidWorks renvoyées par .FrameLeft, .FrameWidth, .FrameTop et .FrameHeight sont définies par Windows en pixels.
    Le rapport entre les deux unités dépend de l’écran lui-même, mais vaut généralement 4/3.

J’ai une position correcte de la fiche au milieu de la fenêtre SolidWorks avec les expressions suivantes, quel que soit l’écran utilisé :

With UserForm1
   .Left = (swApp.FrameLeft + swApp.FrameWidth / 2) * 3 / 4 - (.Width / 2)
   .Top = (swApp.FrameTop + swApp.FrameHeight / 2) * 3 / 4 - (.Height / 2)
End With

Cordialement.
DoubleEcran.swp (115,5 Ko)

1 « J'aime »

@m.blt j’ai testé rapidement, centré sur mon écran de gauche, si je bascule SW sur l’écran de droite c’est décentré.
Je referai un test demain si j’ai le temps.

1 « J'aime »

Même chose que @Cyril.f , @m.blt pas vraiment centré et décalage sur la hauteur, le ratio ne corrige pas l’erreur, et sur plus de 20 poste info j’ai peur que ce soit très aléatoire malheureusement.

Je pense qu’il va falloir mesurer le bon ratio
3/4 ne fonctionne pas sur mon écran de base (pas de deuxième écran)
Jai essayé de voir la fiche technique


Je pense que il va falloir le calculer
(145/25.4/(1920/210.24))=0.62 (le bon ratio pour moi)
Je suppose que cela est le même pour un deuxième écran seulement si ils ont le même ppi
De ce point de vue je propose de travailler avec deux ratio, genre si le nombre de pixels dépasse 1920(par exemple) calculer les premières (ou deuxièmes) pixels par le premier ratio et additionné le reste avec un calcul de l’autre ratio

1 « J'aime »

Bonjour à tous,

Il est vrai que l’utilisation des « points écrans » par VBA pose souvent problème à en juger par les discussions sur différents forums (souvent dédiés à Excel ou Access).
La solution consiste à s’en affranchir en faisant appel aux fonctions API de Windows qui n’utilisent que des pixels.
La macro jointe est une adaptation de la précédente, qui fait le travail sur mon PC avec deux écrans. La fiche UserForm1 est centrée sur la fenêtre de SolidWorks.
Test rapide: si la fenêtre SolidWorks est déplacée, un clic sur le bouton « Centrer » remet en place la Userform.

Cordialement.
DoubleEcran.swp (171,5 Ko)

1 « J'aime »

Bonjour @tous
@m.blt votre macro me surpasse :sweat_smile:.
Alors j’ai essayer de développer la fonction que j’ai évoqué précédemment en tenant compte de votre remarque sur les unités.

Je mets à votre disposition un petit outil simple qui permet de calculer les ratio (j’espère que ça va fonctionner :roll_eyes:)
Macro1.swp (76 Ko)
Macro2.swp (56 Ko)
Doc1.pdf (237,9 Ko)

2 « J'aime »

Tout d’abord, merci beaucoup pour le temps passé, je n’imaginais pas que centrer un userform sur la fenêtre SW serait aussi compliqué!
@Lynkoa15 t’as solution est simple, mais comme cette macro sera utilisé sur plus de 20 postes avec un nombre d’écran(s) de 1 à 2, le plus souvent 2, et de taille et ratio complètement différent.
De plus le problème de ration existe également sur la hauteur. C’est pourquoi je pense me tourné vers la solution de @m.blt qui fonctionne parfaitement.
@m.blt par contre j’ai un peu de difficulté à comprendre ta macro tellement est est complète.
J’avoue atteindre un peu mes limites de développeur autodidact.
J’ai repris ton code dans une macro simplifié avec un userform sans rien edt je n’arrive pas à l’adapté.
Est-on obligé dans l’appel d’avoir les 2 arguments (Textbox1 et 2):
CoincidentsCtresWindows UserForm1.TextBox1, UserForm1.TextBox2, True
et pas simplement
CoincidentsCtresWindows UserForm1 , True
J’ai tenté de modifié ton code sans parvenir à ce que je souhaitais (Centré la fenêtre seulement avec le nom du userform)

Bonjour @sbadenis ,

Désolé, je suis fan de l’adage « Pourquoi faire simple quand on peut faire compliqué ? ».
image

En pièce jointe la macro de centrage de la fenêtre VBA sur la fenêtre SolidWorks, dépouillée de tous les accessoires TextBox, ListBox et autres boutons. Sa seule fonction est de positionner le UserForm VBA au centre de la fenêtre SolidWorks au moment de son premier affichage.
Elle fonctionne sur mon PC, avec un ou deux écrans. Je n’ai pas essayé avec trois…

Les conditions sont les suivantes :

  • SolidWorks est activé (ce qui est en principe le cas puisque la macro est lancée) ;
  • le module principal se nomme CentrageUsrFrm et ne contient que la procédure main;
  • dans la procédure principale (main), le premier paramètre passé à la fonction CoincidentsCtresWindows, est l’intitulé (caption) de la fenêtre SolidWorks, défini en dur : « SOLIDWORKS ».
    Le second paramètre est celui du UserForm, récupéré via sa propriété caption;
  • le module IdentFenetres contient les deux fonctions qui font appel aux API de Windows pour récupérer les dimensions des fenêtres et calculer la position du UserForm. Ce module ne demande en principe aucune modification.

Cordialement.
CentrageUsrFrm.swp (102 Ko)

2 « J'aime »

Cela fonctionne parfaitement comme pour la précédente, en revanche c’est beaucoup plus simple à comprendre maintenant! :crazy_face:
Merci pour les explications et la macro simplifié!
Même si passé par les API windows reste compliqué pour centré une simple fenêtre, cela reste la seul solution viable en tout cas (multipostes et écrans différents)

Bonjour @sbadenis ,

Satisfait de voir que cela vous convient…

Quant à l’utilisation des API de Windows, il n’y a pas vraiment d’autres solutions puisque c’est Windows qui gère les fenêtres des différentes applications. SolidWorks lui-même, quand il renvoie les positions et dimensions de sa propre fenêtre (FrameLeft, FrameWidth…) fait probablement appel aux API de Windows.

On pourrait sans doute « cacher » les deux fonctions du module IdentFenetres dans une dll, ce qui permettrait de supprimer ce module et ne laisserait plus que deux lignes dans la macro pour centrer le UserForm.
Mais c’est l’installation sur différents postes qui deviendrait délicate : emplacement de la dll, enregistrement dans la base de registre de Windows). L’intérêt de la macro, c’est d’être complètement autonome du point de vue de l’installation.

Cordialement.

2 « J'aime »

Oui effectivement c’est bien possible, 'est juste bizarre que solidworks n’ai pas implémenté de quoi simplifier cette fonctionnalité, via une dll par exemple!
Et cela me fera juste un énième module dans ma macro qui est déjà bien fournit, rien d’inquiétant.
Et merci encore.

1 « J'aime »