XL 2016 Quoi de moins simple que de déterminer le RECT d'une fenêtre ? Fichier pour test...

Dudu2

XLDnaute Barbatruc
Bonjour,

Pour des raisons qui m'échappent, les coordonnées d'une fenêtre ont des valeurs farfelues lorsque cette fenêtre est maximisée.
Ainsi:
VB:
With ActiveWindow
    .Left
    .Top
    .Width
    .Height
End With
ne correspondent pas à la réalité, du moins celle qui pourrait servir à position un UserForm aux limites de la fenêtre pas exemple.

Aussi, j'ai dû passer par de l'API pour déterminer l'exact RECT (pixels) d'une fenêtre qui doit rester valide en multi-moniteurs.
Et bingo, bug excel (chez moi en tous cas) lorsque la TaskBar n'est pas en bas sur la fonction API GetClientRect() qui retourne 1 pixel de moins que prévu en Bottom !

Alors j'ai 2 versions de cette fonction utilisateur GetWindowExactRECT et GetWindowExactRECTSimple et j'aimerais que quelques XLDNautes dévoués aux causes perdues fassent le test suivant.
  1. Lancer le fichier ci-dessous
  2. Maximiser la fenêtre Excel si elle ne l'est pas déjà
  3. Pour chaque position de barre des tâches en bas, à gauche, en haut, à droite
    a) - Vérifier que les 2 résultats affichées des RECT de la fenêtre sont identiques
    b) Vérifier qu'ils sont cohérents avec la dimension de l'écran en pixels
Merci par avance.
 

Pièces jointes

  • Test WindowExactRECT.xlsm
    33.8 KB · Affichages: 6
Solution
C'est ça, en fait ça n'a pas tellement de sens de chercher ou d'utiliser le RECT de la fenêtre.
Car en Maximisé, si Excel dit que Left et Top c'est -8 ou -9 c'est que ce sont les valeurs telles qu'il les gère.
Cependant, ce RECT est inexploitable pour positionner un UserForm.

Le seule chose qui soit exploitable c'est le RECT de la fenêtre corrigé des marges qu'on trouve en calculant la différence de largeur et de hauteur entre le GetWindowRECT et le GetClientRECT corrigé du potentiel bug Excel sur le ClientRECT.Bottom quand la fenêtre est maximisée et la barre des tâches pas en bas ou en antohide.
Sans bug Excel c'est moins amusant !

C'est ce que font maintenant la fonction...

patricktoulon

XLDnaute Barbatruc
chez moi le post #13 corrigé
l'userform1 rentre de 1 point a vue d’œil dans la taskbar
et ça correspond bien au 2 -1 en haut et -1 en bas et c'est bon
et le rectangle m'est toujours donné -2 pour le top et 862 pour le bottom
autrement dit je rentre un peu dans la taskbar (en dessous du moins )

pour la taskbar
VB:
Option Explicit

Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Private Declare PtrSafe Function GetWindowRect Lib "user32" _
    (ByVal hWnd As LongPtr, ByRef lpRect As RECT) As Long

Private Declare PtrSafe Function SHAppBarMessage Lib "shell32" _
    (ByVal dwMessage As Long, ByRef pData As APPBARDATA) As Long

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Type APPBARDATA
    cbSize As Long
    hWnd As LongPtr
    uCallbackMessage As Long
    uEdge As Long
    rc As RECT
    lParam As Long
End Type

Private Const ABM_GETSTATE As Long = &H4
Private Const ABS_AUTOHIDE As Long = &H1

Function IsTaskbarVisible() As Boolean
    Dim hwndTaskbar As LongPtr
    Dim rect As RECT
    Dim appBarData As APPBARDATA
    Dim appBarState As Long
    
    ' Trouver la fenêtre de la barre des tâches
    hwndTaskbar = FindWindow("Shell_TrayWnd", vbNullString)
    
    If hwndTaskbar = 0 Then
        ' Barre des tâches introuvable
        IsTaskbarVisible = False
        Exit Function
    End If
    
    ' Vérifier si la barre des tâches est masquée automatiquement
    appBarData.cbSize = LenB(appBarData)
    appBarData.hWnd = hwndTaskbar
    appBarState = SHAppBarMessage(ABM_GETSTATE, appBarData)
    
    If (appBarState And ABS_AUTOHIDE) = ABS_AUTOHIDE Then
        ' En mode masquage automatique
        IsTaskbarVisible = False
        Exit Function
    End If
    
    ' Obtenir la position et la taille de la barre des tâches
    GetWindowRect hwndTaskbar, rect
    
    ' Si la hauteur ou la largeur est 0, elle est masquée
    IsTaskbarVisible = Not (rect.Bottom - rect.Top = 0 Or rect.Right - rect.Left = 0)
End Function

Sub TestTaskbarVisibility()
    If IsTaskbarVisible() Then
        MsgBox "La barre des tâches est visible."
    Else
        MsgBox "La barre des tâches est masquée ou en mode auto-hide."
    End If
End Sub
 

patricktoulon

XLDnaute Barbatruc
tu vois ce petit defaut en haut ben j'ai le même en bas dans la barre des tache
1734805086149.png
 

Dudu2

XLDnaute Barbatruc
Bonsoir les encadreurs de fenêtres,
Grâce à la patience et l'assistance précieuses de @TooFatBoy que je remercie, j'ai enfin pu venir à bout de ce truc.

Remarque:
Le bug Excel qui rend une marge incorrecte à cause d'un ClientRECT.Bottom incorrect existe aussi lorsque la fenêtre n'est pas maximisée en 32 bits.
La marge totale verticale calculée avec ClientRECT.Bottom incorrect est impaire ce qui impossible car la marge totale contient les 2 marges (gauche+droite ou haute+basse) et aucune des marges ne peut être différente de sa réciproque.
SM_CYBORDER c'est 1 en haut et en bas (fenêtre pas maximisée)
SM_CXBORDER c'est 1 à gauche et à droite (fenêtre pas maximisée)
Donc c'est bien un foutu bug.
Le problème c'est que ClientRECT.Bottom incorrect c'est selon les cas +1 ou -1 pixel.
La solution est, pour la marge verticale, d'utiliser la marge horizontale qui semble toujours correcte et toujours applicable à la marge verticale.

Le fichier du Post #13 a été mis à jour en conséquence.

Edit: A noter que, mis à part le module concerné par ce sujet:
- Module_GetClientFromWindowRECT
ce fichier contient 3 modules intéressants pour des développeurs:
- Module_GetTaskBarRectPosAutoHid (pour le RECT, la position et l'autohide de la TaskBar)
- Module_GetUserFormMarginsPoints (pour connaître les marges extérieures des UserForm)
- Module_PointToPixelToPoint (pour convertir des pixels en points et inversement)
 
Dernière édition:

Statistiques des forums

Discussions
315 088
Messages
2 116 089
Membres
112 658
dernier inscrit
doro 76