Microsoft 365 Forcer l'affichage de mon userform (barre de progression) sur l'écran où le classeur est actif (cas des doubles/triples écrans)

Le_Phénomène

XLDnaute Nouveau
Bonjour,

Dans l'un de mes projets, je fais afficher une barre de progression via un userform afin de faire "patienter" l'utilisateur (et histoire que ce dernier ne panique pas trop lors de traitements un peu longuais ;) - ça les rassure) :
1730798875040.png


Sauf que... selon les configurations des uns et des autres, de leur choix d'ouvrir/placer le classeur Excel sur tel ou tel écran (l'équipe dispose tous d'un double écran avec affichage étendu et certain utilise même leur laptop comme troisième écran), mon userform s'affiche toujours par défaut sur l'écran principal définit dans les paramètres Windows.

Donc pas de souci lorsque l'utilisateur à son classeur ouvert sur le moniteur déclaré comme écran principal mais c'est bof lorsqu'il a décidé de placer son classeur sur l'un des écrans secondaire.

Je souhaiterai donc pouvoir :
1- savoir sur quel écran est activé le classeur Excel qui mouline
2- forcer l'affichage de mon userform sur ledit écran

Si un éminant expert à une solution ou une voie sur laquelle je peux m'orienter, je l'en remercie par avance.

En vous souhaitant une bien agréable journée.
Franck
 
Solution
Salut les afficheurs de UserForms,

J'ai amélioré ma petite ressource de Barre de Progression Interruptible (sur option):
pour y ajouter:
- le centrage par défaut dans la fenêtre active
- la possibilité de la positionner Left et Top
- la possibilité de la dimensionner en Width et Height
- la possibilité de désigner la couleur de la barre
- la possibilité de supprimer le Caption (barre de menu système de la fenêtre)

Tous les paramètres sont modifiables en cours d'exécution (à chaque appel) de la barre.

En principe ça devrait convenir à @Le_Phénomène sans avoir à trop bricoler.

Je vous mets le fichier de la...

Dudu2

XLDnaute Barbatruc
Je sais ce que sont les opérateurs booléens et comment ils fonctionnent (c'était la base pour le jeune informaticien que je ne suis plus depuis une centaine d'années), mais si tu as des infos sur le problème posé par cette fonction, alors vas-y...

Avant que tu ne te lances, je te rappelle que le Caption peut être supprimé dans le SetWindowLong() avec l'une ou l'autre de ces constantes (moi, je l'ai testé !):
Private Const WS_DLGFRAME = &H400000
Private Const WS_BORDER = &H800000
Private Const WS_CAPTION = WS_BORDER Or WS_DLGFRAME

Et ce n'est pas parce que je l'ai supprimé avec WS_CAPTION que la fonction doit se focaliser seulement sur cette constante sachant qu'un code quelconque peut l'avoir supprimé avec WS_DLGFRAME ou WS_BORDER.

Edit: C'est la raison pour laquelle j'ai codé:
VB:
    iStyle = GetWindowLongPtr(UserFormHandle, GWL_STYLE)
    If iStyle = (iStyle And Not WS_DLGFRAME) _
    Or iStyle = (iStyle And Not WS_BORDER) Then
        IsBordersAndSystemBarRemoved = True
    End If
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re ben alors tu n'a jamais compris comment ça fonctionnait
quand tu fait par exemple

iStyle = GetWindowLongPtr(UserFormHandle, GWL_STYLE)
SetWindowLongPtr UserFormHandle, GWL_STYLE, iStyle And Not WS_CAPTION

tu peux répéter 20 fois cette opération tu aura toujours le même résultat même si iStyle est différent après la première fois

ce n'est pas moins!!! ws_Caption c'est et pas!!! Ws_Caption

conclusion tout les tests Si ce n'est pas ceci ou celà sont inutiles

vois les constantes comme l'ensemble d'un tableau de properties chacune à sa place dans une address mémoire
quand tu fait And not une constante tu vide la place ou se trouve cette constante dans ce tableau de properties
je dis ça schématiquement en fait c'est une address mémoire
constitution schématisée propertie fenêtre
totale
&h80000bt fermer+barreagrandirreduireresizelong address
&Hc10000&h10000&H20000&H40000&H94C80080

quand tu fait and not tu vide une des cases
quand tu fait OR tu met la valeur dans sa case respective(si elle y est déjà ben ça fait rien)
mais dans tout les cas ta fenêtre aura son tableau entier de properties avec des cases vides ou pas
donc tout test if c'est réduit ou pas ou if border ou pas etc sont absolument inutiles
tu fait et c'est tout ;si c’était déjà fait ben ca change rien ça fait rien
 

Dudu2

XLDnaute Barbatruc
quand tu fait par exemple

iStyle = GetWindowLongPtr(UserFormHandle, GWL_STYLE)
SetWindowLongPtr UserFormHandle, GWL_STYLE, iStyle And Not WS_CAPTION

tu peux répéter 20 fois cette opération tu aura toujours le même résultat même si iStyle est différent après la première fois

En ignorant les zéros qui suivent WS_CAPTION c'est &H8 or &H4 (= &HC) soit 1100 en binaire.
Le but c'est bien de mettre à 0 les 2 bits correspondants pour supprimer le Caption avec WS_CAPTION.
S'ils sont déjà à 0 ils y restent, mais ce qui nous intéresse c'est quand ils sont à 1, ils passer à 0.
Je vois pas où est le problème.

donc tout test if c'est réduit ou pas ou if border ou pas etc sont absolument inutiles
tu fait et c'est tout ;si c’était déjà fait ben ca change rien ça fait rien
Pour revenir à la fonction IsBordersAndSystemBarRemoved(), son rôle n'est pas de définir telle ou telle valeur de bits, c'est de retourner True si le Caption est là et False sinon. Elle ne fait rien sur le Caption, ni le retirer, ni l'ajouter, elle teste les bits de WS_BORDER et de WS_DLGFRAME dans le Window Style.

Ce code ne set rien !
VB:
    iStyle = GetWindowLongPtr(UserFormHandle, GWL_STYLE)
    If iStyle = (iStyle And Not WS_DLGFRAME) _
    Or iStyle = (iStyle And Not WS_BORDER) Then
        IsBordersAndSystemBarRemoved = True
    End If
 

Dudu2

XLDnaute Barbatruc
If iStyle = (iStyle And Not WS_DLGFRAME)

Ce test veut dire que si le Window Style capturé égale le Window Style capturé en retirant le bit de WS_DLGFRAME, alors le Window Style capturé n'a pas le bit de WS_DLGFRAME.

Et donc que le Caption n'est pas là.
 

patricktoulon

XLDnaute Barbatruc
re
c'est pas la valeur ou le contenant c'est l'utilité du test
tu veux l'enlever tu l'enlève (And not)
tu veux le mettre tu le met c'est tout (OR)
il ne peut y avoir d'erreur puisque tu procède en addition logique sur iStyle
istyle est récupéré avec getwindowlong avant
quelque soit la valeur qu'il ai si tu add logiquement ça match
tester si 0 ou 1 est superflu a mon sens

tu utilise des fonction implémenté par ms au travers de ses dll system
pourquoi passer par 1/2/3 fonctions alors que tu obtiens ce que tu cherche par la fonction déjà implémentée par les déclarations d'api ?

si encore c’était un switch automatisé ,je comprendrais

un exemple ou je trouve que c'est justifié par exemple c'est ton GetUserFormHandleByCaption qui là switch sur le findwindowex au cas ou le findwindow donne zero et que peut être le userform a été apparenté a l'app excel
là oui je suis OK
demain je mettrais les test benchmark dessus tes fonctions on analysera les tips pas les temps (quoi que)parce que c'est pas des fonctions lentes mais les tips vont parler à mon avis
 

patricktoulon

XLDnaute Barbatruc
tiens puisque tu semble adepte des operateurs logiques
teste ca avec un userform et deux boutons
VB:
#If VBA7 Then
    #If Win64 Then
         Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #Else
         Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #End If
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
#End If

Private Sub CommandButton1_Click()
    applique True, False, True
End Sub
Private Sub CommandButton2_Click()
    applique False, True, False
End Sub

Sub applique(Optional reduire As Boolean = False, _
             Optional agrandir As Boolean = False, _
             Optional resizeb As Boolean = False)

    Dim H As LongPtr
    H = FindWindow(vbNullString, Me.Caption)
    SetWindowLongPtr H, -16, &H94C80080 _
                                Or &H20000 And reduire _
                                Or &H10000 And agrandir _
                                Or &H40000 And resizeb
End Sub
 

Statistiques des forums

Discussions
314 667
Messages
2 111 705
Membres
111 264
dernier inscrit
Monnoye