merci l'ami ;)
Version imprimable
merci l'ami ;)
a ben mince alors je croyais que l'unité de mesure était en "pied":ptdr: a ben ca alorsCitation:
Désolé pour toi, mais pour VBA, les coordonnées de l'activeWindow sont établies, elles, en POINTS et par rapport non à l'angle supérieur gauche de l'écran, mais à celui de la fenêtre application.
Exactement comme sont établies, par exemple, les coordonnées d'un contrôle d'un userform.
Mais tu ne sais pas appliquer :mouarf:Citation:
a ben mince alors je croyais que l'unité de mesure était en "pied" a ben ca alors
Voilà l'image réduite et moins gourmande
Pièce jointe 279413
Si tu la comprends (elle "parle") tu ne devrais avoir aucune difficulté à placer un userform sans passer par les pixels et des positions par rapport au desktop.
Je n'ai montré là que l'aspect concernant les ordonnées. Celui des abscisses est mille fois moins complexe.
Je vais de bon matin laintenant revenir sur ce que tu as écrit sans sourciller, patricktoulon, à savoir :
Ce ne peut être nickel , patricktoulon, qu'avec un facteur de zomm à 100 %, et ce : quelle que soit la résolution de l'écran.Citation:
c'était une expression "au millimètre prêt"
bref chez moi c'est nickel
Il y a à cela une raison fort simple : -->>
L'l'homothétie parfaite n'existe qu'en mathématiques (géométrie) du seul fait que le point n'est pas matériel et n'a aucune dimension minimum.
-- Un pantographe, une loupe, un projecteur, des verres optiques, etc ... respectent parfaitement cette homothétie
-- Il ne saurait en aller de même avec l'utilisation d'un écran, dont la plus petite partie n'est pas, elle, élastique et a donc des dimensions minimums (celles d'un pixel). Il se trouve que par exemple et entre autres, certaines bordures ont une épaisseur de 1 pixel. Comment penses-tu passer à 0,75 pixels (cela n'existe pas) en facteur de zomm de 75% ? C'est d'ailleurs également un problème dans l'autre sens, en facteur de zoom non multiple entier de 100 .
Alors ? Il y a forcément un décalage (tout l'art est de le rendre le moins significatif possible) dans certains cas. Mais il n'y aura pas le "nickel" que tu dis.
Ce décalage sera plus ou moins important en fonction de la résolution de l'écran (puisque les dimensions d'un pixel en dépendent), mais il, sera toujours présent.
Que se passe-t-il selon toi en arrière plan lorsqu'est utilisé activepane ? Comment sont "estimées" les "corrections" à apporter pour avoir un meilleur "rendu". Que se passe-t-il par ailleurs lorsque l'on passe de conversion en conversion, sinon ce qui se passe en mathématiques lorsque l'on divise, puis multiplie par un facteur ?
Je te laisse à toutes ces réflexions et tes tâtonnements et attends maintenant ton code "corrigé" par "tâtonnements" pour te mettre en face d'une évidence.
A plus.
Bonjour unparia
alors tout ce que tu dis je l'entends bien
ta formule de calcul y a bien longtemps que je l'ai comprise bien avant que tu intervienne même
je sais très bien qu'un pixel n'est pas divisible
et chez moi avec un zoom de 30% a 200% j'ai un résultat visuel nikel
et ma formule est toujours la même
sauf que j'ai une!!!! ligne de code en plus pour la rendre universelle
cette ligne est ajouté car j'ai enfin trouvé le paramètre que toi visiblement ignore encore
ce paramètre est la raison du pourquoi ca marche chez l'un et pas chez l'autre
ce paramètre devra être aussi appliqué a ta formule pour être universel
j'attends d'autre retours(capture d'écran )que j'ai demandé sur un autre forum
une fois tous ces retours reçu je pourrais confirmer mais j'en suis déjà bien convaincu
c'est tellement bête que quand tu saura tu comprendra pourquoi j'ais dis précédemment regarder les capture chez moi et celle de Nicolas
et la c'est pas une puce que je t'ai mis a l'oreille c'est un gros scarabée bien bruyant tu peu pas le rater
Bonjour les copains,
un petit code qui fonctionne nickel pour ma pars et qui permet de remplacer l'api qui fonctionnait aussi, en attendant votre suite
Code:
1
2
3
4
5
6
7
8
9
10
11
12 Private Sub Worksheet_SelectionChange(ByVal Target As Range) Const x As Double = 57 Const y As Double = 12.5 With UserForm1 .Show 0 .StartUpPosition = 0 .Left = ActiveWindow.PointsToScreenPixelsX(ActiveCell.Left) - y .Top = ActiveWindow.PointsToScreenPixelsY(ActiveCell.Top) - x End With End Sub
Ben ...
Il se trouve que je n'ai pas de problèmes non plus. Et sans conversions, avec juste les points de VBA !
J'attends ton "scarabée", donc ... Et le code "universel", dont je passerai les résultats à la loupe, puisque tu dis qu'il est "universel"...
Bonjour Nicolas JACQUIN
Que sont les valeurs en dur que tu indiques ?
EDIT : non, Nicolas : ton code ne fonctionne pas comme attendu du tout, y compris avec zoom 100%
Tout est décalé, surtout horizontalement (énormément)
Avec un zoom autre que 100% -->> pire
Et si la première cellule visible n'est pas la A1 -->> pire encore
Et si on n'affiche pas la barre des titres -->> un décalage de plus encore
Et si on a fait flotter et déplacer la grille (activewindow) -->> la catastrophe totale
Elles n'ont hélas pas grand chose à voir avec de tels décalages (vraiment énormes y compris en situation normale : sans déplacer et sans zoomer)Citation:
vu qu'il y aurait des variantes selon les versions excel
On est loin de petites corrections nécessaires, là
Amitiés
selon les object que tu utilise ca devrait donner ceci
sauf que plus je montele zoom plus le décalage est important pas de quoi fouetter un chat comme on dit chez nous
je n'ai pas prévu les non displaybar comme c'est juste un exercice et que je préfère de loin ma formule
mais je l'ai fait pour que tu vois que j'ai bien compris le principe
quand j'aurais tous mes retours et si tout ce que j'ai remarquer est exact ( je viens d'avoir encore 3 confirmations ce matin)
je donnerais la mienne et tu comprendra pourquoi cette méthode ne peut pas être universelle
mais avec ma formule le décalage est tellement imperceptible
si tout se passe bien tu devrais etre bon et nicolas décalé si ca c'est pas un indice heinCode:
1
2
3
4
5
6
7
8
9
10
11
12
13 Sub test24() With UserForm1 Dim BarFormul#, BarHeading#, UsableW#, Ruban#, Rattrapage#, Zooom# BarFormul = .Height - .InsideHeight BarHeading = (.Height - .InsideHeight) UsableW = (Application.Width - Application.UsableWidth) Ruban = (Application.Height - Application.UsableHeight) - BarFormul Rattrapage = (.Width - .InsideWidth) Zooom = (ActiveWindow.Zoom / 100) .Show 0 .Left = Application.Left + ActiveWindow.Left + UsableW + ((BarHeading + 2) * Zooom) + ([b3].Left * Zooom) .Top = Application.Top + ActiveWindow.Top + Ruban + BarFormul + (BarHeading * Zooom) - Rattrapage + ([b3].Top * Zooom) End With
Ah bon ! Heureux de l'apprendre ...Citation:
mais avec ma formule le décalage est tellement imperceptible
Il se trouve qu'il est très nettement visible (pas du tout "imperceptible") sur ma machine, tant horizontalement que verticalement (plus de 5 fois supérieur au mien !)
Tu expliques cela comment ? Avec un autre "scarabée" ?
Tu sais quoi, patricktoulon ? tu as pigé (et appliqué) une partie (la hauteur "intouchable" qui n'est pas QUE le "ruban") de ce que je t'ai dit et du dessin que je t'ai fait, mais a "zappé" tout le reste !
Il y a des flèches partout, sur mon dessin ... et des commentaires à bien lire.
autant pour moi
c'est toi qui doit avoir le décalage et Nicolas qui doit être bon
je n'en dis pas plus pour le moment j'attend la fin des test avec toutes versions confondues
ce serait bien que nicolas passe par la et fasse le test pour voir
avec ton code tel quel ça me donne ça, capture plein écran
Pièce jointe 279457
oui j'avais pigé depuis longtemps
app.top+ruban =intouchable
displaybar =oui ou non
si displayheading=non alors pas de colonne de numéro de ligne pour le left
c'est pas compliqué
mais tout ca avec ma formule je le fait en une fois
mais selon un cas très précis de configuration logiciel il faut rattraper
et la je viens de te le donner l'indice
Je vois que ce scarabée a des difficultés à sortir de sa bouse ...
On va l'y aider :
Commencer par mettre les propriétés qui ne faussent pas :
les deux les plus évidentes --->>
BorderStyle = fmBorderStyleNone
SpecialEffect = fmSpecialEffectFlat
(Et ce n'est pas tout).
non je suis pas dans la bouz j'au eu une inter toute la journée samedi pouurri!!!!!
j'ai testé élément par élément avant de faire l'assemblage et tout ce qui doivent être touché par le zomm ne répondent pas correctement en fonction du pourcentage
et avant que tu réponde sache que j'ai très bien compris la logique
ta beau tourner ca dans tout les sens c'est pas une solution universelle
un seul bemol et de taille celui la c'est que tu utilise les cotes userform pour trouver une cote qui est dans l'activewindow
parti de la ca peut être bon comme tout mauvais notamment entre W7 et W +++ si ca c'est pas indice
parti de la ta logique n'est pas bonne
je te signale quand même qu'avant de parler j'ai testé sur W7 windows 10 et windows 8.1
pour être honnête j'ai installé Windows 10 sur un partition j'ai donc pu testé moi même, même si j'ai eu les retours qui confirment ma théorie
Tu voudras bien m'excuser, mais j'attends donc ton code "universel" que je passerai à la loupe.
Tant que cela ne sera pas là : ce ne sera que du baratin et rien d'autre, si tu le permets ...
J'attends donc tout simplement ce "petit" cela (ton "scarabée", quoi ...) ;)
Bonjour les amis,
j'ai passé la nuit dessus après un essai un peu laborieux, j'ai réussi, pour moi ça fonctionne au millimètre (Windows 10 et Excel 2016)
et avec n'importe quel zoom
J'attends vos réactions ;)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Long) As Long Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long Function PositionForm(Form As Object, rng As Range) Dim K As Double, Z As Double Z = ActiveWindow.Zoom / 100 K = GetDeviceCaps(GetDC(0), 88) / 72 K = GetDeviceCaps(GetDC(0), 90) / 72 lleft = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K - 5 ttop = ActiveWindow.PointsToScreenPixelsY(rng.Top * K * Z) / K PositionForm = Array(lleft, ttop) End Function Sub TestUserform() r = PositionForm(UserForm1, ActiveCell) With UserForm1: .Show 0: .Left = r(0): .Top = r(1): End With End Sub
Bonjour Nicolas JACQUIN
D'abord : Je te félicite pour le travail que tu as fait. Il mérite totalement ceci -->> :applo::applo:
Le résultat obtenu est parfait en ce qui concerne le positionnement vertical
Il ne l'est pas (plusieurs pixels de décalage) en ce qui concerne le positionnement horizontal
Ton résultat (également exact en position verticale sur ma machine) est la preuve de ce que les calculs (déjà en ce qui concerne la position verticale) ne dépendent absolument pas d'un "scarabée" d'une version
Je te tire personnellement mon chapeau pour t'y être mis. Tu es courageux et ne t'éparpille pas.
- le défi reste d'y parvenir sans utilisation de fonctions de l'Api de Windows
Re, voici sans API, moi ça marche , quand on monte dans les grand zoom il y à léger décalage, pas loin du but
;)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 Function PositionForm(FORM As Object, rng As Range) Dim K As Double, Z As Double Z = ActiveWindow.Zoom / 100 K = ((ActiveWindow.ActivePane.PointsToScreenPixelsX(ActiveSheet.[A1].Width) - ActiveWindow.ActivePane.PointsToScreenPixelsX(0)) / ActiveSheet.[A1].Width) / Z lleft = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K - 6 ttop = ActiveWindow.PointsToScreenPixelsY(rng.Top * K * Z) / K PositionForm = Array(lleft, ttop) End Function Sub TestUserform() r = PositionForm(UserForm1, ActiveCell) With UserForm1: .Show 0: .Left = r(0): .Top = r(1): End With End Sub
Tu auras ainsi toujours un décalage, dès que tu t'écarteras du zoom 100 %.Citation:
quand on monte dans les grand zoom il y à léger décalage
Le fait est tout simplement qu'il est bien évidemment plus visible en allant vars de grand zooms.
Il est clair que pour le même décalage relatif, le décalage absolu est plus ou moins visible (repérable visuellement) selon qu'on agrandit ou que l'on rapetisse.
Ce décalage est dû à la conjugaison de deux choses, auxquelles j'ai fait allusion plus haut :
- un pixel (plus petite partie graphique) ne peut être représenté avec exactitude en conservant ses proportions si on lui applique un coefficient
- il y a toujours perte de précision lorsque l'on fait successivement des opérations inverses (multiplication/division) sur un nombre
Corriger cela est possible, mais alors sans passer par des conversions d'unités graphiques et ainsi :
- en reprenant (en l'ayant "soupçonnée") la manière dont Microsoft a fait ses calculs pour garder à la fois précision et un rendu acceptable des traits. Il a tout simplement distingué dans ses calculs ce qu'il y a entre les bordures et les bordures elles-mêmes. Cela est particulièrement vrai, entre autres, pour le traitement de la barre de titres de la feuille active.
J'ai fais une légère correction, avec ou sans API, ça tombe précis chez moi. (Windows 10 et Excel 2016)
Avec API
Et sans APICode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Long) As Long Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long Function PositionForm(Form As Object, rng As Range) Dim K As Double, Z As Double Z = ActiveWindow.Zoom / 100 K = GetDeviceCaps(GetDC(0), 88) / 72 K = GetDeviceCaps(GetDC(0), 90) / 72 lleft = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K - 5 ttop = ActiveWindow.PointsToScreenPixelsY(rng.Top * K * Z) / K PositionForm = Array(lleft, ttop) End Function Sub TestUserform() r = PositionForm(UserForm1, ActiveCell) With UserForm1: .Show 0: .Left = r(0): .Top = r(1): End With End Sub
Je remerci toutefois Patrick et Unparia pour leurs aides (ou chamailleries je sais pas :zen: ), qui m'ont permis d'en arriver là. :ave:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 Function PositionForm(FORM As Object, rng As Range) Dim Z As Double, K As Double Z = ActiveWindow.Zoom / 100 K = ((ActiveWindow.ActivePane.PointsToScreenPixelsX(ActiveSheet.[A1].Width) - ActiveWindow.ActivePane.PointsToScreenPixelsX(0)) / ActiveSheet.[A1].Width) / Z lleft = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K - 6 ttop = ActiveWindow.PointsToScreenPixelsY(rng.Top * K * Z) / K PositionForm = Array(lleft, ttop) End Function Sub TestUserform() r = PositionForm(UserForm1, ActiveCell) With UserForm1: .Show 0: .Left = r(0): .Top = r(1): End With End Sub
ta proposition sans fonction de l'api de windows présente un décalage horizontal d'environ 2 pixels
Ce qui ne va pas, c'est la valeur -6 fixée en dur pour ce qui est du left et qui dépend de la résolution de l'écran (nombre de pixels par point horizontalement).
Que se passe-t-il sur ta machine en transformant ainsi ta fonction (calcul séparé de K et K1:
Code:
1
2
3
4
5
6
7
8
9
10
11 Function PositionForm(FORM As Object, rng As Range) Dim Z As Double, K As Double Z = ActiveWindow.Zoom / 100 K = ((ActiveWindow.ActivePane.PointsToScreenPixelsX(ActiveSheet.[A1].Width) - ActiveWindow.ActivePane.PointsToScreenPixelsX(0)) / ActiveSheet.[A1].Width) / Z K1 = ((ActiveWindow.ActivePane.PointsToScreenPixelsY(ActiveSheet.[A1].Width) - ActiveWindow.ActivePane.PointsToScreenPixelsY(0)) / ActiveSheet.[A1].Width) / Z lleft = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K ttop = ActiveWindow.PointsToScreenPixelsY(rng.Top * K1 * Z) / K1 PositionForm = Array(lleft, ttop) End Function
ça revient au même que si je retire le -6
Pièce jointe 280118
j'avais déjà essayé ça
d'après la capture de nicolas vous être en train de trifouiller le paramètre que j'essaie de vous indicer depuis 3 jours
nicolas ton code tel quel me done ca :
Pièce jointe 280131
je suppose que unparia doit avoir le même résultat avec W10 et 2007 tandis que Nicolas est bon avec W et 2010
et aussi que votre "-6" donne le résultat opposé l'un de l'autre hein!!!!?????
ca y est vous voyez la
Oui comme tu disais, cela dépend surement de la version, je peux pas mettre en mode petite fenêtre comme toi pour voir ce que ça donne, moi ça colle au poil fenêtre réduite ou pleine écran
cadeau
et oui la différence n'est que entre w10 et 2007 pour les autres sauf retour négatifs que je n'ai pas encore eu pour 2016Code:cadre = IIf(Application.OperatingSystem Like "*/*" And application.version= 12, 0, 6)
autrement dit w7 2007 =cadre
w10 2007 =pas cadre
les autre rien
pour quoi me direz vous hein???
et bien il suffit de regarder nos captures et de voir qu'avec w7 l'userform a un cadre les autres non
par contre avec w10 le shell prend en charge l'affichage des fenêtres mémé les thunderframes(userform) et comme il n'a pas de cadre pour l'affichage des fenêtres dans W10 je vous le donne dans le mille
voila maintenant vous savez
oupss j'ai corriger le mot répété dans le code
Non patricktoulon, je n'ai pas la combinaison de version que tu dis.
A Nicolas JACQUIN :
Ton approche m'intéresse énormément, mais pas au prix d'une estimation en fonction de la/les version(s).
Nous allons, si tu veux bien, faire une petite expérience dont je souhaite connaître les résultats sur ta machine.
Elle a pour but de tenter de déterminer la véritable largeur totale de la bordure + titres de lignes
ATTENTION / à ce stade, je ne m'intéresse qu'à ce positionnement horizontal, sans encore traiter le scroll horizontal éventuellement utilisé.
Test à faire donc avec colonne A visible et première colonne
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 Function PositionForm(FORM As Object, rng As Range) Dim G As Double, D As Double, K As Double, Z As Double Z = ActiveWindow.Zoom / 100 K = GetDeviceCaps(GetDC(0), 88) / 72 G = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K D = ActiveWindow.PointsToScreenPixelsX((rng.Left + rng.Width) * K * Z) / K K = GetDeviceCaps(GetDC(0), 90) / 72 'lleft = ActiveWindow.PointsToScreenPixelsX(rng.Left * K * Z) / K - 0 '==> on va essayer autrement ttop = ActiveWindow.PointsToScreenPixelsY(rng.Top * K * Z) / K corr = (ActiveWindow.Width - ActiveWindow.UsableWidth + 3) * Z lleft = Application.Left + ActiveWindow.Left + corr + (ActiveCell.Left * ActiveWindow.Zoom / 100) PositionForm = Array(lleft, ttop) End Function Private Sub CommandButton5_Click() Z = ActiveWindow.Zoom / 100 r = PositionForm(UserForm1, ActiveCell) With UserForm1 .Show 0: .Left = r(0): .Top = r(1) End With End Sub
ça donne
Pièce jointe 280146
unparia c'est quoi ta config ? vu les capture (dessin) que tu a posté il me semble bien reconnaitre 2007
Présentement : 2007 pour Office mais sur XP
Mais s'il faut passer par des si telle combinaison alors, sinon si ... etc ...
Je préfère alors ne pas profiter de calculs déjà faits et faire les miens, même si plus nombreux. ;)
Constat : si le fait de cadre ou pas cadre changeait quoi que ce fût, cela voudrait alors dire que les conversions internes du genre PointsToScreenPixelsX, PointsToScreenPixelsY de Microsoft Office comportent en elles-mêmes des erreurs ou omissions de calculs ;)
Je commence pour tout dire à me demander si ce ne sont pas les effets d'ombrage dont je vois qu'est doté le userform de Nicolas JACQUIN, qui, dans leur traitement, ne "déplacent" pas quelque peu le userform vers la droite !
Je ne sait plus quoi faire de mieux, comme je disais, avec ma config c'est au poil.
Après c'est sur que ça doit changer selon le système d'exploitation et de la version excel, plus tous les systèmes de personnalisation d'apparence selon les système.
Désolé pour les autres mais là je pense que s'il faut tenir compte de chaque paramètre ça va être compliqué, là je pense que c'est plus du cas par cas.
re
oui les ombrage y sont aussi pour quelque chose sur w7 aussi
nous savons que tout ce qui est au dessus de la lite d'entête colonne n'est pas touché par le zoom on est bien d'accords
et pourtant faite cette expérience résultat faux ou non on s'en fout les démentions ayant été calculées sur mon pc
c'est pas le but de l'expérience mais plutôt le comportement du zoom
faite le en zoom 100 puis augmentez le zoom et réessayez
la je suis perplexe :lol:
alors si vous avez une explication digne de ce nom faite tournerCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 Sub test() Set cible = [D3] Set app = Application: Set actw = ActiveWindow: Set usf = UserForm1 Z = (actw.Zoom / 100) With actw.ActivePane: pppx = (.PointsToScreenPixelsX(3) - .PointsToScreenPixelsX(0)) / 3: End With Caption = usf.Height - usf.InsideHeight onglet = 19 ruban = (CommandBars("Ribbon").Height / pppx) - onglet - Caption formulbar = 19 headingbar = 18 * Z cadre = (app.Width - app.UsableWidth) - 1 With UserForm1 .Show 0 .Left = 150 .Top = app.Top + actw.Top + Caption + onglet + ruban + formulbar + Caption ' + headingbar .Height = 150 End With End Sub
j'ai fait à 100 110 120
Pièce jointe 280165
Pièce jointe 280166
Pièce jointe 280168
Pour moi la barre A B C .... des colonnes grandissent en hauteur avec le zoom et verticalement 1 2 3 .... pareils
oui je sais ca mai tu a vu que le userform est prevu pour etre juste au niveau de la barre de formule en aucun cas le zoom devrait apporter une modification