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

XL 2016 VBA - Comment passer une structure Private en argument d'une fonction ?

Dudu2

XLDnaute Barbatruc
Bonjour,

On peut passer en argument d'une fonction une structure Public ByRef.
Excel refuse de le faire avec une structure Private.



Y a-t-il un moyen détourné de le faire en la mappant sur son adresse ou autre ?
 

Pièces jointes

  • Classeur1.xlsm
    22 KB · Affichages: 8

Dudu2

XLDnaute Barbatruc
En effet, le String fout la pagaille. Je ne comprends pas qu'il passe sans problème en 64 bits.
Ceci dit quelque chose ne va pas car j'obtiens:

Alors que a chaine passée est "ABC".
 

patricktoulon

XLDnaute Barbatruc
je rectifie
j'ai essayé ta version basique avec 3 variable long dans le mt
et ca crash immédiatement aussi
c'est donc bien un problème de taille total de l'adress memoire le lenB donne une erreur
et par conséquent c'est bien un problème de long longptr ou je ne sais quoi
la version de chatGPT fonction car il agrandi un peu avec le converttostring mais la raison qu'il invoque n'est pas tout a fait exacte
je vais lui transmettre mes observations pour voir ce qu'il en pense
il pourra peut être ajuster son explication
 

Dudu2

XLDnaute Barbatruc
Dans la version de ChatGPT y a un truc qui ne va pas.
VB:
' Lire la longueur de la chaîne à partir de la mémoire
    CopyMemory StrLen, ByVal Ptr - 4, 4 ' Longueur Unicode
MsgBox StrLen
La longueur copié de la zone mémoire qui contient la longueur indique le nombre de bytes et pas la StrLen().
Le MsgBox donne bien 6 donc il n'y a pas matière à faire fois 2:
Code:
ReDim Buffer(0 To (StrLen * 2) - 1) ' Chaque caractère = 2 octets (Unicode)
        CopyMemory Buffer(0), ByVal Ptr, StrLen * 2
 

patricktoulon

XLDnaute Barbatruc
je te retransmet le test que je fait avec chatGPT
voici le resultat du test que je lui a donné
Code:
Private Type MONTYPE   
L1 As Long   
L2 As Long   
S As String
End Type
Sub TestCopyMemory()   
Dim MT As MONTYPE   
Dim MTAdd As LongPtr   
Dim DataSize As Long       
MT.L1 = 12345    MT.L2 = 67890    MT.S = "Test"   
' Vérifiez la taille    DataSize = LenB(MT)   
Debug.Print "Taille mémoire calculée : " & DataSize   
' Vérifiez l'adresse mémoire avant de la passer à CopyMemory   
MTAdd = VarPtr(MT)   
Debug.Print "Adresse mémoire : " & MTAdd        ' Appel à la fonction CopyMemory    'Call b(MTAdd, DataSize)
End Sub

et le resultat dans ma console

Taille mémoire calculée : 12
Adresse mémoire : 13627592


ChatGPT a dit :​

Merci pour votre retour. Voici quelques points importants à analyser à partir de vos résultats :

  1. Taille mémoire calculée (12 octets) :
    • Vous avez déclaré un type MONTYPE contenant deux variables Long et une chaîne String.
    • En VBA, la taille d'un Long est de 4 octets.
    • Une chaîne en VBA a une structure particulière. En général, la chaîne String occupe une certaine quantité de mémoire pour stocker sa longueur et ses caractères. Pour une chaîne comme "Test", cela devrait être plus que 4 octets pour stocker la longueur de la chaîne et les caractères eux-mêmes.
      En fait, chaque chaîne en VBA utilise 2 octets pour stocker la longueur (en caractères), plus 2 octets par caractère pour les chaînes à longueur fixe. Par conséquent, une chaîne "Test" de 4 caractères (donc 8 octets pour les caractères) + 2 octets pour la longueur = 10 octets au total pour cette chaîne.
    Vous avez donc une estimation totale de 12 octets qui semble correcte :
    • 2 Long = 8 octets
    • 1 String = 4 octets (pour la longueur et la mémoire interne pour les caractères).
  2. Adresse mémoire (13627592) :L'adresse mémoire semble valide et montre que l'objet MT a bien été créé en mémoire, mais il est important de noter que dans le cas de types complexes comme un String, l'adresse réelle de la chaîne à l'intérieur de l'objet MONTYPE pourrait être différente de celle de la structure elle-même.

Problème potentiel avec CopyMemory et le String :​

Lorsque vous utilisez CopyMemory, il peut y avoir un problème en raison de la gestion des chaînes en VBA. Le type String dans VBA utilise un encodage interne (souvent UTF-16), et il y a une longueur de chaîne qui est stockée en plus des caractères réels.

Si vous utilisez CopyMemory pour copier une structure qui contient un String, cela peut interférer avec le traitement de la mémoire de la chaîne, car cette mémoire interne contient la longueur de la chaîne en plus des caractères.
 

Dudu2

XLDnaute Barbatruc
J'ai corrigé la fonction PtrToString() en utilisant une String de travail dans la fonction au lieu d'un Array de Bytes. Et maintenant j'ai bien la totale.



Edit: validé en 32bits et 64bits
 

Pièces jointes

  • Test copymemory VarPtr String et Structure.xlsm
    25.4 KB · Affichages: 1
Dernière édition:

Dudu2

XLDnaute Barbatruc
Alors c'est bien, on sait passer des Structure Private en paramètres des fonctions grâce à leur VarPtr().
Quand il y a des String dans la structure c'est un peu plus délicat.

Mais pour un Type MONITORINFO c'est simple, pas de String.
J'ai testé ce fichier dans mon Office 2016 32 bits et je n'ai pas le problème sur les Types Private retournés par les fonctions (en l'occurrence un RECT). A essayer chez toi.

Edit: Fichier modifié 24/12/2024 à 17h57
 

Pièces jointes

  • Test TaskBar RECT Multi-Moniteurs.xlsm
    89 KB · Affichages: 2
Dernière édition:

patricktoulon

XLDnaute Barbatruc
et ben voila ca marche chez moi aussi
maintenant tu a tout ce que tu cherchais
tu a donc maintenant quelque chose de compatible avec 64/32 moyennant eventuellement si cette version ne fonctionne pas en 64 de faire un switch ta méthode celle de chatGPT
 

patricktoulon

XLDnaute Barbatruc
je sais pour monitorinfo
monitor info est une structure qui elle même contient des autres structrures
chatGPT m'a conseiller de transmettre en variable tableau ConvertstructToArray fonction perso que j'ai abandonné car maintenant avec mon ScreenCatalog j'ai Absolument tout ce dont j'ai besoins et c'est utilisable dans tout les modules
je peux te mettre la version finale dans l'autre post si tu veux

je travaille en ce moment sur l’attachement d'une fenêtre ou positionnement relatif
car en effet on a les deux possibilités
le tout c'est de faire des codes propres et intelligibles
et en même temps je prépare des petit confitsdans des verines pour ce soir j'ai déjà pris au moins 1 kilo
j'ai la patronne qui chante aux armes citoyen
je suis déjà condamné
m'en fou yen a fout
 

TooFatBoy

XLDnaute Barbatruc
Je n'ai toujours pas compris l'intérêt de se forcer à limiter la portée des variables et de pondre une usine à gaz pour contourner le problème engendré, Mais faut dire que tout ça me dépasse largement un pneu...


Sinon, est-ce normal qu'il y ait une erreur de compilation avec #39 ?
 

Discussions similaires

Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…