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

XL 2016 Window.PointsToScreenPixelsX vs Pane.PointsToScreenPixelsX

Lu76Fer

XLDnaute Occasionnel
Sujet : éclaircir la différence existant entre ces deux fonctions appartenant à 2 objets différents
Bien-sûr il y a aussi la fonction PointsToScreenPixelsY et c'est le pendant pour calculer l'ordonnée d'un point sur la grille, sur l'écran.
En faite, la fonction Pane.PointsToScreenPixelsXouY est apparue dans la version d'Excel 2007, sous 2003 il n'y avait que Window.PointsToScreenPixelsX ouY et il est resté par soucis de compatibilité ascendante.

Window.PointsToScreenPixelsX : cette fonction permet de calculer la position sur l'écran d'une grandeur sur la grille Range.Top ou Range.Left, sur l'écran en travaillant sur l'ActivePane. Il s'agit du volet actif et il peut y en avoir 4,2 ou 1 selon le nombre de séparateur ... Cette fonction ne tient pas compte du Zoom sur la grille et même avec un zoom à 100% donne une position approximative ?!? En faite la seule information utile que peut donner cette fonction c'est pour la position du Volet Actif :

VB:
x = ActiveWindow.PointsToScreenPixelsX(0)
y = ActiveWindow.PointsToScreenPixelsY(0)
Cela peut vous permettre de connaitre la position de la grille mais de façon très indirecte ... Il faut être sur le volet 1 et avoir la cellule A1 visible dans celui-ci.

Pane.PointsToScreenPixelsX : cette fonction fait la même chose sur le volet Pane, tient compte du zoom et donne la position exacte !


Conclusion : n'utilisez pas ActiveWindow.PointsToScreenPixelsXouY mais ActiveWindow.Panes(i).PointsToScreenPixelsXouY si vous ne souhaitez pas vous prendre inutilement le choux !
 

Dudu2

XLDnaute Barbatruc
Bonjour,
Encore faut-il savoir dans quel Pane se trouve l'objet (cellule, Shape, etc...) manipulé.
Voici une fonction qui permet de le faire.
VB:
'----------------------------------------------------
'Pane de l'objet dont le parent est la feuille active
'- Visible = True, l'objet doit être visible
'- Visible = False, l'objet peut être visible ou non
'----------------------------------------------------
Private Function ObjectPane(Obj As Object, Optional Visible As Boolean = True) As Pane
    Dim Rng As Range
    Dim i As Integer
    Dim Pan As Pane
    Dim PosRow As Integer
    Dim PosColumn As Integer
 
    'Le Parent de l'objet n'est pas la feuille
    If Not Obj.Parent Is ActiveSheet Then Exit Function
   
    With ActiveWindow
   
       'Selon le type d'objet
       Select Case True
           Case TypeOf Obj Is Range
               Set Rng = Obj
   
           Case Else
               Set Rng = Obj.TopLeftCell
       End Select
 
        '--------------------------------
        'L'objet peut être visible ou non
        '--------------------------------
        If Not Visible Then
            If .SplitRow = 0 Then
                PosRow = 1
            Else
                If Rng.Row <= .SplitRow Then PosRow = 2 Else PosRow = 3
            End If
   
            If .SplitColumn = 0 Then
                PosColumn = 1
            Else
                If Rng.Column <= .SplitColumn Then PosColumn = 4 Else PosColumn = 5
            End If

            Select Case PosRow * PosColumn
                Case 1, 2, 4, 8
                    Set Pan = .Panes(1)
                Case 3, 5, 10
                    Set Pan = .Panes(2)
                Case 12
                    Set Pan = .Panes(3)
                Case 15
                    Set Pan = .Panes(4)
            End Select
 
        '-------------------------
        'L'objet doit être visible
        '-------------------------
        Else
            'Recherche du Pane de l'objet si visible
            For i = 1 To .Panes.Count
                If Not Intersect(Rng, .Panes(i).VisibleRange) Is Nothing Then Exit For
            Next i
            If i <= .Panes.Count Then Set Pan = .Panes(i)
        End If
    End With
 
    'Return Value
    Set ObjectPane = Pan
End Function
 

patricktoulon

XLDnaute Barbatruc
re
Bonjour tout les deux
et j'en rajoute une couche car @Dudu2 n'a jamais pris ce qui a fut un grand debat
la ou je ne suis pas d'accords avec @Dudu2 c'est ici

VB:
 Case Else
               Set Rng = Obj.TopLeftCell
       End Select

pour la simple et bonne raison que si la pane est scrollée(par exemple) et donc que la shape(ou l'object) est un peu caché peut être même un peu la cellule aussi et là tout tes calculs sont faussés puisque ca te donnera une coordonnée de la panne precedente a gauche ou en haut suivant les cas

d'autre part je me suis rendu compte depuis quelque jours que depuis la version W10 22H2 avant j'avais la 21
et bien le zoom windows n'interfère plus avec les calcul de coeffpixel contrairement à la version W10 22h2 et surtout W 7

autrement dit avec ce W10 que je sois en 100% ,125% , 150% , ou plus
le coeef point to pixel à appliquer est toujours (/1.333333333333333) ou (*0.75)
perso j'ai simplifié mon moteur de conversion point to pixel avec pointtoscreenpixels(X ou Y)
en contrôlant la bonne panne sans tout le calcul que je faisait avec les splitrow et splitcolumn ce que fait @Dudu2 encore
le panne(x).visiblerange a un top , un left, un width , un heigth
il est facile de retrouver une element et sa panne

et pour info aussi loin que je me souvienne même sur 2003 window(x).pointoscreenpixel donnait déjà une donnée éronnée
c'est pour ça que même Microsoft la dépréciait cette fonction et déconseillait de l'utiliser

avec la venu de W7 il avaient arrangé un peu la chose avec la prise en compte des panes

conclusion
pour W7 faire attention au zoom excel et au zoom windows pour d'eventuels calculs de conversion
pour W10 y en a plus rien à fout'

attention aussi a une feuille fractionnée sans freezpane un élément peut être sur toute les panes
 
Dernière édition:

Lu76Fer

XLDnaute Occasionnel
Voici un bout de code qui peut répondre à ce problème (ce n'est pas de moi) :
VB:
Public Function QuelPane(ByVal T As Range, Optional ByVal ActivationFeuil As Boolean = False) As Pane
Dim LngNbPanes As Long, LngPane As Long
 
    If ActiveWindow.VisibleRange.Worksheet.Parent.Name = T.Worksheet.Parent.Name Then
        If ActiveWindow.ActiveSheet.Name = T.Worksheet.Name Or ActivationFeuil Then
            T.Worksheet.Activate
            LngNbPanes = ActiveWindow.Panes.Count
            For LngPane = 1 To LngNbPanes
                With ActiveWindow.Panes(LngPane)
                    If Not Intersect(T, .VisibleRange) Is Nothing Then
                        Set QuelPane = ActiveWindow.Panes(LngPane)
                        Exit Function
                    End If
                End With
            Next
        End If
    End If
    Set QuelPane = Nothing
End Function
 

Dudu2

XLDnaute Barbatruc
Bonjour @patricktoulon,

Oui je me souviens en avoir longuement discuté avec toi.
Mais ça:
je ne comprends pas ce qui pose problème.
Évidemment que si l'objet n'est pas visible à cause d'un Scroll, les coordonnées rendues par un PointsToScreenPixels n'ont pas de sens pour un positionnement. C'est pourquoi dans la fonction, il y a un option Visible:
Private Function ObjectPane(Obj As Object, Optional Visible As Boolean = True) As Pane

attention aussi a une feuille fractionnée sans freezpane un élément peut être sur toute les panes
Oui, c'est sûr. Dans ce cas la fonction rendra la 1er Pane où l'objet apparaît ce qui correspond au Pane lorsque les volets sont figés.

Je vais vérifier ton histoire de Zoom qui ne s'appliquerait plus.
 

Dudu2

XLDnaute Barbatruc
Alors tu as raison, peut-être faut-il apporter une correction à cette notion de Visible.
Car en effet, si l'objet n'est pas Visible (pas dans le VisibleRange) ça peut être pour 2 raisons:
- sa TopLeftCell est Scrollée auquel cas le PointsToScreenPixels n'a pas de sens.
- sa TopLeftCell n'est pas Scrollée mais hors du cadre auquel cas le PointsToScreenPixels a un sens.

C'est donc la notion de VisibleRange qui ne va pas !
 

Dudu2

XLDnaute Barbatruc
Voilà la fonction qui va bien:
VB:
'----------------------------------------------------
'Pane de l'objet dont le parent est la feuille active
'Hidden = False : l'objet ne doit pas être dans la partie cachée (scrollée) du Pane
'Visible = True : l'objet doit être dans le VisibleRange du Pane
'----------------------------------------------------
Private Function ObjectPane(Obj As Object, _
                            Optional Hidden As Boolean = False, _
                            Optional Visible As Boolean = False) As Pane
    Dim Rng As Range
    Dim i As Integer
    Dim Pan As Pane
    Dim PosRow As Integer
    Dim PosColumn As Integer
 
    'Le Parent de l'objet n'est pas la feuille
    If Not Obj.Parent Is ActiveSheet Then Exit Function
  
    With ActiveWindow
        'Selon le type d'objet
        Select Case True
            Case TypeOf Obj Is Range
               Set Rng = Obj
  
            Case Else
                Set Rng = Obj.TopLeftCell
        End Select
 
        '---------------
        'Pane de l'Objet
        '---------------
        If .SplitRow = 0 Then
            PosRow = 1
        Else
            If Rng.Row <= .SplitRow Then PosRow = 2 Else PosRow = 3
        End If

        If .SplitColumn = 0 Then
            PosColumn = 1
        Else
            If Rng.Column <= .SplitColumn Then PosColumn = 4 Else PosColumn = 5
        End If

        Select Case PosRow * PosColumn
            Case 1, 2, 4, 8
                Set Pan = .Panes(1)
            Case 3, 5, 10
                Set Pan = .Panes(2)
            Case 12
                Set Pan = .Panes(3)
            Case 15
                Set Pan = .Panes(4)
        End Select

        '------------------------------------------------
        'L'Objet doit être dans la partie visible du Pane
        '------------------------------------------------
        If Not Hidden Then
            If Rng.Row < Pan.ScrollRow _
            Or Rng.Column < Pan.ScrollColumn Then
                Set Pan = Nothing
            End If
        End If
        
        '----------------------------------------------
        'L'Objet doit être dans le VisibleRange du Pane
        '----------------------------------------------
        If Visible Then
            If Intersect(Rng, Pan.VisibleRange) Is Nothing Then
                Set Pan = Nothing
            End If
        End If
    End With
 
    'Return Value
    Set ObjectPane = Pan
End Function
 

Pièces jointes

  • ObjectPane.xlsm
    26.7 KB · Affichages: 4

Dudu2

XLDnaute Barbatruc
et bien le zoom windows n'interfère plus avec les calcul de coeffpixel contrairement à la version W10 22h2 et surtout W 7
Je sais pas d'où tu sors ça (peut-être W7) mais je ne le constate pas chez moi W10 à jour.

Par exemple ce fichier (Edit: aussi en Ressource) qui utilise du Pan.PointsToScreenPixelsX et Pan.PointsToScreenPixelsY pour positionner un UserForm fonctionne parfaitement avec ou sans zoom sur la feuille.

D'ailleurs, si ces fonctions Excel n'étaient plus sensibles au Zoom ce serait une quasi extinction de masse des codes VBA.
 

Pièces jointes

  • VBA Positionner un UserForm sur un Objet d'une feuille (Simple).xlsm
    33.4 KB · Affichages: 4
Dernière édition:

Lu76Fer

XLDnaute Occasionnel
Je possède Windows 7 et il n'y a jamais eu de différence ! Le but est de s'entraider de toute façon et certain ne sont pas là pour ça visiblement et ne produise rien de fonctionnel au niveau du code .
 

Dudu2

XLDnaute Barbatruc
@Lu76Fer,
Tu es nouveau ici. Sache que @patricktoulon est un immense contributeur grâce à qui j'ai appris plein de choses.
Pour t'en convaincre, voies sa dernière ressource publiée. Rien d'équivalent dans l'univers !
 

Lu76Fer

XLDnaute Occasionnel
Je n'ai rien vu de convaincant jusque là bien au contraire !
 

patricktoulon

XLDnaute Barbatruc
Je n'ai rien vu de convaincant jusque là bien au contraire !
et c'est un nouveau qui le dit hein
surtout qui n'a même pas pris la peine de regarder si quelqu'un ou même plusieurs avait déjà précisé dans les ressource ou ailleurs ce point qui fait l'objet de son post#1






@Dudu2 avant sur W 7 quand on réglait la taille des caracteres sur W7 dans les paramètre d'affichage
on avait le choix
100%
125%
150%
et là prêtez y attention je parle du zoom windows ou le (DPI)mais pas du zoom excel

ma fonction ptopx sur W7
donnait en 100% 1.333333333333333 (plus ou moins c'est pas precis avec les arrondi vba même en CDEC)
donnait en 125% 1.6666666666667(plus ou moins c'est pas precis avec les arrondi vba même en CDEC)
donnait en 150% 2(plus ou moins c'est pas precis avec les arrondi vba même en CDEC)
et les coefficients étaient bons (plus ou moins c'est pas precis avec les arrondi vba même en CDEC)

maintenant sur W10 22h2 xxxxxxxxxxx


maintenant que je soit en 100 ou 125 ou 150 % ma fonction donnera toujours 1.33333333xxxxxxx
c'est pas ultra précis mais ça on le sait
mais visiblement microsoft a modifié la gestion MDI
et le zoom WINDOWS

je vous fait une démo sur W10 si vous voulez
 

Dudu2

XLDnaute Barbatruc
Ok, tu parles du zoom Windows. Fallait quand même préciser !
Mais je me souviens que ta fonction "Pixel to Point" (je parle pas de celle qui va lire le Registre) utilise des PointsToScreenPixels, on en avait aussi discuté car cela générait des résultats approximatifs chez moi en variant le Zoom Excel, raison pour laquelle j'avais abandonné cette méthode pour revenir sur l'API de base.
Je vais quand même faire des essais. Après une tite sieste sous ventilateur
 

patricktoulon

XLDnaute Barbatruc
oui le zoom window
mais le zoom excel on doit l'utiliser dans la fonction pttopx qui utilise pointstoscreenpixel sinon ça ne fonctionne pas alors oui c'est approximatif mais 8 ou 9 chiffres après la virgule est ce bien important
surtout que la on parle de pixel ca fait mème pas un quart de pixel

après si tu veux la fonction par la base de registre elle fonctionne sur Windows 10 aussi
VB:
Function PtoPx()
  With CreateObject("WScript.Shell"): PtoPx = .RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ThemeManager\LastLoadedDPI") / 72: End With
 End Function
 
Sub test()
MsgBox PtoPx
End Sub
et la aussi en zoom windows 100 , 125 , 150 elle donnera toujours 1.333333333333333

ta fonction getpane pourrait se résumer à ça
VB:
Function GetPaneOfObject(obj As Object) As Pane
   'patricktoulon
   Dim ob
    If TypeName(obj) <> "Range" Then Set ob = obj.TopLeftCell Else set ob = obj
    With ActiveWindow
        For I = 1 To .Panes.Count
            If Not Intersect(.Panes(I).VisibleRange, ob) Is Nothing Then Set GetPaneOfObject = .Panes(I)
        Next
    End With
End Function
 
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…