XL 2016 Quoi de moins simple que de déterminer le RECT de la barre des tâches en multi-moniteurs ? Fichier pour test...

Dudu2

XLDnaute Barbatruc
Bonjour,

La barre des tâches en multi-moniteurs, je ne sais pas bien sur quel(s) moniteur(s) elle se trouve ni ou exactement ni ce qu'elle contient. Y a des tas d'options.

Ici j'aimerais seulement considérer sa position en moniteur et pour ça j'ai 3 options à vérifier en multi-moniteurs avec le fichier de test ci-joint.

XLDNautes multi-monitoristes, pourriez-vous SVP utiliser le fichier joint et pour chacun de vos moniteurs indiquer quels sont parmi les 3 options, les résultats valides de position de la barre des tâches. Avec screenshots joints si possible.

Merci par avance.
 

Pièces jointes

  • TaskBar RECT Multi-Moniteurs.xlsm
    102.4 KB · Affichages: 2
Dernière édition:
Solution
J'ai monté un multi-moniteurs avec mon Laptop en double écran avec le moniteur de mon Desktop.

La sentence est tombée:
- SEUL le calcul de différence rcWork et rcMonitor issus de MONITORINFO donne le RECT de la TaskBar dans un moniteur donné.
- Les autres (SHAppBarMessage et la Window "Sell_TrayWnd" ne retournent que le RECT de la TaskBar sur le moniteur principal. Donc inutiles en multi-moniteurs.

Et même la position d'un TaksBar peut varier d'un moniteur à un autre et là encore il faut la déterminer sur la base des rcWork et rcMonitor.

Le fichier joint contient 3 modules:
  1. Module_GetMonitorInfoFromWindow
    La fonction GetMonitorInfoFromWindow() retourne la structure MONITORINFO pour la fenêtre...

Dudu2

XLDnaute Barbatruc
en faisant la soustraction rcmonitor-rcwork de chaque moniteur tu devrait avoir ton rectangle et par la même occasion ça te donne une indication sur sa position
Oui, c'est ce que fait la 1ère fonction qui titre "TaskBar RECT by difference rcWork & rcMonitor"
Mais je voulais savoir ce que donnent les 2 autres qui à mon avis ne vont répondre que sur le moniteur principal, encore que je ne sois pas sûr à 100% selon où se trouve la Window Excel.

En fait je vais passer en multi-moniteurs avec un Laptop pour tester, pas simple pour moi, mais c'est plus sûr que de demander des tests à des personnes plus ou moins disponibles et ne faisant les tests et leur reporting que selon leur humeur du moment, ce que je comprends parfaitement.

Quant à la position de la TaskBar, on peut effectivement la déduire du "TaskBar RECT by difference rcWork & rcMonitor" SAUF si la TaskBar est en AutoHide auquel cas la fonction SHAppBarMessage avec un ABM_GETTASKBARPOS répond toujours sur la position, même en AutoHide.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Le problème pour récupérer les rcWork et rcMonitor d'un moniteur qui donnent à coup sûr la position de la TaskBar c'est qu'il faut faire le tour du monde avec un EnumDisplayMonitors(). J'aurais aimé avoir une fonction plus simple.

Il y a bien GetMonitorInfo() mais il faut le Handle du moniteur et si on peut le trouver avec MonitorFromWindow() on ne peut pas le trouver par un numéro de moniteur, en tous cas je n'ai rien trouvé.
 

patricktoulon

XLDnaute Barbatruc
pour le moment j'ai concu ce petit truc
j'ai essayé de le faire corrigé par chatGPT mais même lui aussi bloque sur les index device et devicename
le principe oui ben un enum est nécessaire malheureusement
sauf que je le fait une fois et je stock les infos dans un type et je dimensionne un tableau de type
comme ça tu le fait qu'une fois et tu te sert de mesmonitors(x) pour choper ce dont tu a besoins
après sincèrement le enum est instantané
j'ai quelques pistes intéressantes aussi avec WMI et oui surprenant en même tant pas tant que ça
alors voila la bête
à terme dans le tableau de type tu devrais avoir
HandleMonitor
index
Width
Height
WorkWidth
WorkHeight
AsTaskbar
TaskBarWeight
IsPrincipal
DeviceIndex
DeviceName

et je mettrait en place la position de la barre aussi ".position(gauche/droite/botomm/top)
avec le simple calcul des rcmonitor et rcwork

là j'ai pas le temps je pars pour la journée en intervention pour un petit jeune qui a fait des conneries
je vais lui tirer un peu les oreilles lui restructurer un peu la boite crânienne ça va me defouler un peu
🤪 🤪 yen a marre d’être toujours enfermé

VB:
' Déclaration des fonctions nécessaires
Declare PtrSafe Function EnumDisplayMonitors Lib "user32" ( _
                              ByVal hdc As LongPtr, ByVal lprcClip As LongPtr, _
                              ByVal lpfnEnum As LongPtr, ByVal dwData As Long) As Long

Declare PtrSafe Function GetMonitorInfo Lib "user32" Alias "GetMonitorInfoA" ( _
                              ByVal hMonitor As LongPtr, ByRef lpmi As monitorInfo) As Long

Declare PtrSafe Function EnumDisplayDevices Lib "user32" Alias "EnumDisplayDevicesA" ( _
                              ByVal lpDevice As String, ByVal iDeviceNum As Long, _
                              ByRef lpDisplayDevice As DISPLAY_DEVICE, ByVal dwFlags As Long) As Long

' Déclaration de types et structures
Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Type monitorInfo
    cbSize As Long
    rcMonitor As RECT ' Dimensions du moniteur
    rcWork As RECT ' Dimensions de l'espace de travail
    dwFlags As Long ' 1 = Moniteur principal
End Type

Type DISPLAY_DEVICE
    cb As Long
    DeviceName As String * 32
    DeviceString As String * 128
    StateFlags As Long
    StateImage As Long
    DeviceID As String * 128
    DeviceKey As String * 128
End Type

Type DataMonitor
    HandleMonitor As Long
    index As Long
    Width As Long
    Height As Long
    WorkWidth As Long
    WorkHeight As Long
    AsTaskbar As Boolean
    TaskBarWeight As Long
    IsPrincipal As Boolean
    DeviceIndex As Long
    DeviceName As String
End Type

' Constantes
Const MONITORINFOF_PRIMARY As Long = &H1
Public MesMonitors() As DataMonitor
Dim x As Long

Sub ListMonitors()
    x = 0
    ReDim MesMonitors(1 To 1) ' Initialisation du tableau

    Dim result As Long
    result = EnumDisplayMonitors(0, 0, AddressOf MonitorEnumProc, 0)
    MsgBox MesMonitors(1).TaskBarWeight
End Sub

' Fonction de rappel pour EnumDisplayMonitors
Function MonitorEnumProc(ByVal hMonitor As LongPtr, ByVal hdcMonitor As LongPtr, _
                         ByRef lprcMonitor As RECT, ByVal dwData As Long) As Long
    Dim monitorInfo As monitorInfo
    monitorInfo.cbSize = Len(monitorInfo)

    ' Incrémenter l'index et redimensionner le tableau
    x = x + 1
    ReDim Preserve MesMonitors(1 To x)

    ' Récupérer les informations du moniteur
    If GetMonitorInfo(hMonitor, monitorInfo) Then
        With MesMonitors(x)
            .index = x
            .Width = monitorInfo.rcMonitor.Right - monitorInfo.rcMonitor.Left
            .Height = monitorInfo.rcMonitor.Bottom - monitorInfo.rcMonitor.Top
            .WorkWidth = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left
            .WorkHeight = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top
            .AsTaskbar = monitorInfo.rcMonitor.Right * monitorInfo.rcMonitor.Bottom <> monitorInfo.rcWork.Right * monitorInfo.rcWork.Bottom
            .IsPrincipal = (monitorInfo.dwFlags = MONITORINFOF_PRIMARY)
            .HandleMonitor = hMonitor
            If monitorInfo.rcMonitor.Bottom <> monitorInfo.rcWork.Bottom Then .TaskBarWeight = Abs(monitorInfo.rcMonitor.Bottom - monitorInfo.rcWork.Bottom)
            If monitorInfo.rcMonitor.Right <> monitorInfo.rcWork.Right Then .TaskBarWeight = Abs(monitorInfo.rcMonitor.Right - monitorInfo.rcWork.Right)

            ' Obtenir le périphérique d'affichage à partir de EnumDisplayDevices
            Dim displayDevice As DISPLAY_DEVICE
            displayDevice.cb = Len(displayDevice)

            ' Nous allons utiliser l'index du moniteur pour interroger EnumDisplayDevices
            If EnumDisplayDevices("", x - 1, displayDevice, 0) Then
                .DeviceIndex = x
                .DeviceName = Trim(displayDevice.DeviceName) ' Exemple : DISPLAY1, DISPLAY2, etc.
            Else
                .DeviceIndex = -1 ' Aucune information trouvée
                .DeviceName = "Non trouvé"
            End If

            ' Affichage dans le débogueur
            'Debug.Print "Moniteur " & .index & " détecté :"
            'Debug.Print " Dimensions totales : (" & monitorInfo.rcMonitor.Left & ", " & monitorInfo.rcMonitor.Top & ") - (" & _
                         monitorInfo.rcMonitor.Right & ", " & monitorInfo.rcMonitor.Bottom & ")"
           
        End With
    End If

    ' Continuer l'énumération
    MonitorEnumProc = 1
End Function

voila bonne journée
Patrick
 

patricktoulon

XLDnaute Barbatruc
ben oui et ça rentre dans le cadre de ton autre discussion aussi
on peut ajouter autant de properties que tu veux et tu le lance qu'une seule fois ou quand tu en a besoins si changement
je n'ai pas réussi a stocker le "DISPLAY1" 2 et 3 ETC....
si j'arrive a faire ça le display1 le le met dans mesmonitors(1) etc..
mais j'arrive pas a le chopper ce devicename et deviceindex
 

Dudu2

XLDnaute Barbatruc
J'ai monté un multi-moniteurs avec mon Laptop en double écran avec le moniteur de mon Desktop.

La sentence est tombée:
- SEUL le calcul de différence rcWork et rcMonitor issus de MONITORINFO donne le RECT de la TaskBar dans un moniteur donné.
- Les autres (SHAppBarMessage et la Window "Sell_TrayWnd" ne retournent que le RECT de la TaskBar sur le moniteur principal. Donc inutiles en multi-moniteurs.

Et même la position d'un TaksBar peut varier d'un moniteur à un autre et là encore il faut la déterminer sur la base des rcWork et rcMonitor.

Le fichier joint contient 3 modules:
  1. Module_GetMonitorInfoFromWindow
    La fonction GetMonitorInfoFromWindow() retourne la structure MONITORINFO pour la fenêtre Excel passée en paramètre.

  2. Module_GetMonitorInfoMonitorNum
    La fonction GetMonitorInfoFromMonitorNumber() retourne la structure MONITORINFO pour le moniteur passé en paramètre.

  3. Module_GetTaskBarRECTMonitorInf
    La fonction GetTaskBarRECTFromMonitorInfo() qui retourne le RECT de la barre des tâches pour la structure MONITORINFO passée en paramètres.
    La fonction GetTaskBarPositionFromMonitorInfo() qui retourne la position de la barre des tâches pour la structure MONITORINFO passée en paramètres.
 

Pièces jointes

  • TaskBar RECT Multi-Moniteurs.xlsm
    101.2 KB · Affichages: 1
Dernière édition:

patricktoulon

XLDnaute Barbatruc
je suis content de te l'entendre dire
quand je disais dans l'autre discussion "tu fait tout avec rcmonitor et rcwork "hein ;)
c'est pour ça que je suis en train de te faire le truc qui contiendra tout
pour ca et ne le faire qu'une fois a l'allumage du fichier par exemple ou au besoin
parfois les choses simples sont bien meilleures
et je te réserve même une surprise
mais je bloque sur ce P... de device
a ben je l'ai dit ici aussi
et encore heureux que l'on ai ça sinon on serait bien mal fichu
parce que si vba est issu de vb il n'en a pas tout les com
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
je ne suis pas loin de terminer
VB:
' Déclaration des fonctions nécessaires
Declare PtrSafe Function EnumDisplayMonitors Lib "user32" ( _
                              ByVal hdc As LongPtr, ByVal lprcClip As LongPtr, _
                              ByVal lpfnEnum As LongPtr, ByVal dwData As Long) As Long

Declare PtrSafe Function GetMonitorInfo Lib "user32" Alias "GetMonitorInfoA" ( _
                              ByVal hMonitor As LongPtr, ByRef lpmi As monitorInfo) As Long

Declare PtrSafe Function EnumDisplayDevices Lib "user32" Alias "EnumDisplayDevicesA" ( _
                              ByVal lpDevice As String, ByVal iDeviceNum As Long, _
                              ByRef lpDisplayDevice As DISPLAY_DEVICE, ByVal dwFlags As Long) As Long

' Déclaration de types et structures
Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Type monitorInfo
    cbSize As Long
    rcMonitor As RECT
    rcWork As RECT
    dwFlags As Long ' 1 = Moniteur principal
End Type

Type DISPLAY_DEVICE
    cb As Long
    DeviceName As String * 32
    DeviceString As String * 128
    StateFlags As Long
    StateImage As Long
    DeviceID As String * 128
    DeviceKey As String * 128
End Type

Type DataMonitor
    HandleMonitor As Long           'Handle du moniteur
    index As Long                   'Index du moniteur
    Width As Long                   'Largeur du moniteur en pixel
    Height As Long                  'Hauteur du moniteur en pixel
    WorkWidth As Long               'Largeur de l'espace de travail disponible en pixel
    WorkHeight As Long              'Hauteur de l'espace de travail disponible en pixel
    AsTaskbar As Boolean            'La taskbar est presente (bouleen)
    TaskBarWeight As Long           'Épaisseur de la taskbar
    TaskbarRECT As RECT             'Le rectangle de la taskbar
    TaskbarPosition As String       'La position de la taskbar en string ("left" ; "top" ; "right" ; "bottom")(minuscule)
    IsPrincipal As Boolean          'Est l'ecran principal(bouleen)
    DeviceIndex As Long             'Index de moniteur selon le system( ne fonctionne pas encore)
    DeviceName As String            'Nom du device ("DISPLAY1" ; "DISPLAY2" ; etc...)
    ScreenWorck As RECT             'Rectangle de l'espace disponible à l'ecran(sans la barre de tache)
End Type

' Constantes
Const MONITORINFOF_PRIMARY As Long = &H1
Public MesMonitors() As DataMonitor
Dim x As Long

Sub ListMonitors()
    x = 0
    ReDim MesMonitors(1 To 1) ' Initialisation du tableau

    Dim result As Long
    result = EnumDisplayMonitors(0, 0, AddressOf MonitorEnumProc, 0)

    If MesMonitors(1).AsTaskbar Then

        With MesMonitors(1).TaskbarRECT
            mess = "Rectangle de la taskBar" & vbCrLf & _
                    "TaskBarPosition : " & MesMonitors(1).TaskbarPosition & vbCrLf & _
                    "Left : " & .Left & vbCrLf & _
                    "Top : :" & .Top & vbCrLf & _
                    "right : " & .Right & vbCrLf & _
                    "Bottom : :" & .Bottom
        End With
        MsgBox mess
        Else: MsgBox "la staskbar n'est pas visible sur cet écran"
    End If
End Sub

' Fonction de rappel pour EnumDisplayMonitors
Function MonitorEnumProc(ByVal hMonitor As LongPtr, ByVal hdcMonitor As LongPtr, _
                         ByRef lprcMonitor As RECT, ByVal dwData As Long) As Long
    Dim MinF As monitorInfo
    Dim RcM As RECT, RcW As RECT
    MinF.cbSize = Len(MinF)
    ' Incrémenter l'index et redimensionner le tableau
    x = x + 1
    ReDim Preserve MesMonitors(1 To x)

    ' Récupérer les informations du moniteur
    If GetMonitorInfo(hMonitor, MinF) Then
        With MesMonitors(x)
            RcM = MinF.rcMonitor
            RcW = MinF.rcWork
            .ScreenWorck = RcW
            .index = x
            .Width = RcM.Right
            .Height = RcM.Bottom
            .WorkWidth = RcW.Right - RcW.Left
            .WorkHeight = RcW.Bottom - RcW.Top
            .AsTaskbar = False
            .IsPrincipal = (MinF.dwFlags = MONITORINFOF_PRIMARY)
            .HandleMonitor = hMonitor

            If RcM.Top < RcW.Top And RcM.Left = RcW.Left And RcW.Right = RcM.Right Then 'OnTop
                .TaskbarRECT = RcM: .TaskbarRECT.Bottom = RcW.Top: .AsTaskbar = True
                .TaskBarWeight = RcW.Top: .TaskbarPosition = "top"

            ElseIf RcM.Bottom > RcW.Bottom And RcM.Left = RcW.Left And RcW.Right = RcM.Right Then 'Bottom
                .TaskbarRECT = RcM: .TaskbarRECT.Top = RcW.Bottom: .AsTaskbar = True
                .TaskBarWeight = RcM.Bottom - RcW.Bottom: .TaskbarPosition = "bottom"

            ElseIf RcM.Left < RcW.Left And RcM.Top = RcW.Top And RcW.Right = RcM.Right Then 'gauche
                .TaskbarRECT = RcM: .TaskbarRECT.Right = RcW.Left: .AsTaskbar = True
                .TaskBarWeight = RcW.Left: .TaskbarPosition = "left"

            ElseIf RcM.Right > RcW.Right And RcM.Top = RcW.Top Then 'droite
                .TaskbarRECT = RcM: .TaskbarRECT.Left = RcW.Right: .AsTaskbar = True
                .TaskBarWeight = RcM.Right - RcW.Left: .TaskbarPosition = "right"
            End If
'***********************************************************************************************
            ' Obtenir le périphérique d'affichage à partir de EnumDisplayDevices
            Dim displayDevice As DISPLAY_DEVICE
            displayDevice.cb = Len(displayDevice)

            ' Nous allons utiliser l'index du moniteur pour interroger EnumDisplayDevices
            If EnumDisplayDevices("", x - 1, displayDevice, 0) Then
                .DeviceIndex = x
                .DeviceName = Trim(displayDevice.DeviceName) ' Exemple : DISPLAY1, DISPLAY2, etc.
            Else
                .DeviceIndex = -1 ' Aucune information trouvée
                .DeviceName = "Non trouvé"
            End If
'**********************************************************************************************

        End With
    End If

    ' Continuer l'énumération
    MonitorEnumProc = 1
End Function
c'est pas beau ça
je cherche toujour pour le device
je ne sais pas si tu te rend compte mais tu a tout
 

Statistiques des forums

Discussions
315 127
Messages
2 116 506
Membres
112 765
dernier inscrit
SIDIANW