Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

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
 

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:

Dudu2

XLDnaute Barbatruc
J'annonce ici le prochain sujet qui va défrayer la chronique et susciter les polémiques les plus violentes...
Quoi de moins simple que de déterminer le RECT de la barre des tâches en multi-moniteurs ?
J'ai déjà 3 options qu'il faut que je présente proprement dans un fichier de test et dont je ne sais pas pour 2 d'entre elles si elles fonctionnent en multi-moniteurs dont les possesseurs seront sollicités.
 

patricktoulon

XLDnaute Barbatruc
Bonjour
perso je m'intéresse à celle ci de discussion
Au final tu dis que:
getwindowrect ne donne pas le bon rectangle
que getclientrect t'en donne un autre et qu'une opération de soustraction ou addition permet d'avoir le bon rectangle
dans ton fichier tu ajoute même la DWM qui fait je ne sais quoi (tout du moins dans ton exemple)

et ben moi je persiste et signe de te dire que tu a tout faux
tout ce que tu fais est une approximation aussi bonne soit elle

Alors oui en effet le getwindowrect sur le handle d'une fenêtre maximisée donne( - quelque chose) en left et en top (chez moi -8 et -8), c'est un bug(si tant est que l'on puisse appeler ça un bug )c'est tout simplement parce que l'on a pas accès avec les api window a la classe UTM car l'accès N°1 que l'on a c'est le desktop

mais bon bref

quand on rectifie ce petit soucis par exemple sur la fenêtre excel ,getwindowrect te donne parfaitement le bon rectangle
et quand je contrôle avec DWM ( je parle de la version que je 'tai donné il y a au moins 2 ans)
et bien mon rectangle DWM a les mêmes données que getwindowrect sans correction

ça veux dire quoi selon toi ?
et bien je te le dis les rectangles après correction des -(pour le maximisé et rien pour le fenêtré) sont parfaitement exacts

oui mais alors que se passe til pour quoi mon userform placé au left et top de mon application n'est pas à la bonne place
la déjà là quand on observe le phénomène dans l'ordre on commence a comprendre
on comprend quoi : et bien que depuis W10 22h2 l'application excel ne subit plus le DWM comme avec windows7 par exemple
par contre les userforms OUI !!!

donc au final tu essaie de placer un userform dont l'affichage est géré par la DWM avec les coordonnées d'une fenêtre qui ne subit pas le DWM

comment tu fait ?: ben en enlevant un peu ceci ou ajoutant cela et je parle du clientrect et les bordures de getsystemmùetrics et tout icouinti qui n'ont rien avoir avec cet écart d'affichage

Alors certes oui au bout d'un moment on arrive a quelque chose encore heureux

sauf que tu zigzag pour avoir un résultat qui est à ta portée déjà sans tout ton bourrin

démonstration
mon écran paramétré a 1600 par 900


ma fonction getwindowrect pour l'application
pas de moins clientrectangle et sm_border et autres cochonneries
d'ailleurs pas un seul caractère numérique dans le code pour extraire ou ajouter quoi que ce soit
VB:
Sub testQ()
    Dim Rc As RECT
    Rc = ApplicationRECT
    mess = "Left : " & Rc.Left & vbCrLf & _
            "Top : " & Rc.Top & vbCrLf & _
            "Right : " & Rc.Right & vbCrLf & _
            "Bottom : " & Rc.Bottom
    MsgBox mess
End Sub
Function ApplicationRECT() As RECT
    Dim R1 As RECT, Tm, Lm&
    R1 = WINDOWRECTANGLE(Application.hwnd)
    If Application.WindowState = xlMaximized Then Tm = R1.Top: Lm = R1.Left
    R1.Left = R1.Left - Lm
    R1.Top = R1.Top - Tm
    R1.Right = R1.Right + Lm
    R1.Bottom = R1.Bottom + Tm
    ApplicationRECT = R1
End Function

demo maximisé

860+les 40 de la taskbar ça me fait 900 on est bon
non maximisé c'est pas la peine que je montre le code est tellement simple hein
voyons voir maintenant en faisant simplement la comparaison donc
en mettant le userform au left top et.. comme ça en point sans api
et en corrigeant avec la simple comparaison du getwindowrect(qui est parfaitement juste je le rappelle) avec le rectangle de DWM et appliquons la correction

Alors pour conclure
quoi de moins simple que de déterminer le rect d'une fenêtre
ben moi je réponds rien le getwindowrect le fait très bien tout seul
à partir du moment ou on sait quand prendre en compte le DWM ou pas

voilà mon cher @Dudu2 quand tu auras compris quand et comment se servir de certaines Api tes codes deviendrons limpides
 
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…