IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Magnétiser une UserForm à la fenêtre d'Excel


Sujet :

Contribuez

  1. #1
    Membre du Club
    Homme Profil pro
    Formateur en informatique
    Inscrit en
    Septembre 2006
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Formateur en informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 53
    Points : 44
    Points
    44
    Par défaut Magnétiser une UserForm à la fenêtre d'Excel
    Remplace le sujet http://www.developpez.net/forums/d14...fenetre-excel/

    Les questions pour positionner une UserForm sont légions c'est que le besoin existe. Comme je ne trouvais pas de solutions complètes et satisfaisante, je m'y colle.
    Ce projet ne pose aucune difficulté particulière pour les personnes connaissant les modules de classes et l'A.P.I. Windows.

    Cahier des charges

    L'utilisateur doit pouvoir afficher le formulaire à des positions précises (Nord - Sud - Sud Est - Ouest - etc.) ou librement.

    Le formulaire doit "suivre" Excel quand sa fenêtre est déplacée ou redimensionnée.
    Cela n'a de sens que si l'utilisateur choisi d'afficher le formulaire en mode vbModeless, puisque en mode modal, il ne peut pas déplacer ou dimensionner la fenêtre Excel (lol).

    Enfin le traitement doit pouvoir s'appliquer à n'importe quel formulaire.

    Architecture

    L'utilisateur créé une procédure qui appelle le point d'entré (procédure FormMagnet du module pkg_Magnet).
    Il passe divers paramètres, nom du formulaire, position, etc. (module pkgSample).

    Le point d'entré met en place un Timer pour "écouter" Excel puis créé l'instance de la classe CUserForm qui gère l'affichage.
    Le timer averti le programme qu'il faut déplacer notre formulaire.
    Ce Timer est codé dans un simple module pkgTimer (idéalement, ce devrait être une classe, c'est dans ma TOUTOU list).

    Plusieurs autres classes sont nécessaires pour récupérer les "mesures" d'Excel. Elles sont toutes manipulées par la classe CUserForm.

    • CAppInfo
    • CScreen
    • CScreenConvert


    Techniques

    Pour récupérer les dimensions et positions encore faut-il s'entendre sur la zone à considérer.

    • Au plus haut niveau nous avons la fenêtre Excel, elle contient les menus et barres d'outils ou les onglets.
    • La barre de formule et d'adresses viennent se loger dessous.
    • Enfin on trouve une zone que l'on pourrait appeler le "bureau Excel".
      C'est dans cette zone que viennent s'afficher les classeurs et c'est la zone que j'utiliserais car je ne souhaite pas que l'UserForm s'affiche sur la barre d'onglets.

    Remarque : avec un peu d'adaptation, on pourrait "aimanter" non pas au bureau mais au classeur (encore un truc dans ma TOUT DOUX list).

    Il existe des zones complémentaires à prendre en compte pour plus de précisions ce sont les bordures et barres de défilement.

    Pour appliquer le traitement à n'importe quel formulaire, il faut que la classe CUserForm soit indépendante. Les instructions du style Set myForm = UserForm1 sont donc interdites.

    En mode vbModeless, il serait possible d'exécuter 2 formulaires simultanément et ce n'est pas souhaitable. Un contrôle est mis en place pour empêcher ce comportement.

    Coding

    Plusieurs moyens s'offrent à nous pour récupérer les mesures.

    Les propriétés Excel.
    Excel travaille avec essentiellement 4 informations Top - Left - Width - Height.
    Ces deux dernières sont déclinés en utilisant la zone utilisable UsableWidth et UsableHeight, c'est la zone que j'apelle le "Bureau" Excel.

    Les A.P.I. Windows
    Lorsque l'on ausculte la liste des classes d'Excel chargées dans Windows avec un outil de Spy, on retrouve nos zones.
    Nom : excel-spy.jpg
Affichages : 573
Taille : 55,2 Ko

    XLMAIN représente l'application Excel.
    Nom : excel-class-main.jpg
Affichages : 566
Taille : 11,6 Ko

    XLDESK c'est la zone utilisable.
    Nom : excel-class-desk.jpg
Affichages : 549
Taille : 4,3 Ko


    La classe EXCEL7 représente le classeur, c'est celle qu'il faudrait utiliser pour "magnétiser" au classeur.
    Les autres classes ne sont pas utiles au projet, d'ailleurs certaines restent obscures et peu de documentation existe.
    • EXCEL;
      La partie gauche de la barre de formule (le symbole de l'assistant fonction).
      Inclu la barre d'adresse.
    • ComboBox : La liste des noms de cellules (barre d'adresse).


    • EXCEL< : Zone d'édition de la barre de formule.
    • EXCEL2
      The four command bar docking areas (top, left, right and bottom). Comment : my english is poor as my larfeuille.


    • MsoCommandBar : A command bar.
    • EXCELE
      A window used to provide in-sheet editing of embedded charts. Comment : see my previous comment.
    • EXCEL4 : Barre de statut.
    • EXCELI
    • EXCELH
    • EXCELG
    • XLCTL

    L'intérêt de passer par l'A.P.I. c'est qu'elle donne des informations complémentaires à savoir les positions droite et basse de la zone considérées.
    En utilisant les mesures de l'application cela n'offre aucun intérêt puisque nous possédons les propriétés Left et Top.
    Mais pour la zone utilisable, Excel ne propose que Width et Height (les dimensions) ce qui est insuffisant, il manque la position.

    Récupérer les informations données par Windows
    En premier lieu il faut récupérer les handles des diverses zones, pour ensuite reprendre les informations souhaitées. C'est le rôle de la classe CAppInfo.
    Pour les mesures des barres de défilement et bordures de fenêtres, c'est la classe CScreen qui le prend en charge.

    Enfin Windows et VB n'utilisent pas la même unité de mesure (les cons !), le premier utilise le pixel alors qu'Excel le twips.
    La classe CConvert calcule le ratio à appliquer pour la conversion en fonction de l'écran.

    Appliquer le traitement quelque soit le formulaire
    Excel propose la collection UserForms de l'objet VBA qui permet de parcourir les formulaires par un indice.
    Ainsi pour ajouter un formulaire, il suffit de l'ajouter à la collection VBA.UserForms.Add ("NomFormulaire").
    Pour le manipuler il suffit d'aller à l'indice du formulaire et l'utiliser comme l'objet.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    VBA.UserForms.Add ("NomFormulaire")
    VBA.UserForms(0).Caption = "Titre"
    VBA.UserForms(0).Show vbModeless
    À la fermeture du formulaire, l'élément est détruit de la collection.

    Écouter Excel
    Il existe un timer dans Excel Application.OnTime. Mais pour plus de précisions, j'utilise le Timer version A.P.I. Windows.
    Le timer est déclenché sur la procédure point d'entrée. À la fermeture du formulaire le timer est arrêter pkgTimer => EndTimer.
    Le timer attend en paramètre la fonction à exécuter. C'est la procédure pkgMagnet => TimerProc, où les anciennes et nouvelles mesures sont comparées et qui agit en conséquence.

    Usage
    Inserer une UserForm et écrire les deux lignes suivantes sur l'évènement , surtout ne pas oublier ces deux lignes !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Private Sub UserForm_Terminate()
     EndTimer
    Set myFormUser = Nothing
    Remarque
    Si le formulaire était toujours affiché en mode vbModal, je pourrais écrire ces deux lignes à la fin de la procédure point d'entrée pkg_Magnet => FormMagnet().
    Mais le comportement de vbmodeless qui poursuit l'exécution du code quand l'UserForm est affichée m'en empêche, ce qui me gène fortement.
    Si quelqu'un sait comment contourner ce comportement !
    Il y aurait bien la possibilité de faire une boucle de temporisation, mais c'est loin d'être propre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Do While VBA.UserForms(0).Visible
       DoEvents
    Loop
    Le code est largement commenté, il a été créé à l'aide d'Excel 2010 32 bits sur Windows 7 - 32 bits et n'a pas été testé dans d'autres conditions.
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. Erreur fatale au lancement d'une UserForm sous Excel 2003
    Par Le POlonais dans le forum Macros et VBA Excel
    Réponses: 22
    Dernier message: 27/11/2007, 17h03
  2. valeur d'une cellule excel dans une userform
    Par kbakouan dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 29/06/2007, 15h38
  3. Réponses: 35
    Dernier message: 18/05/2006, 18h30
  4. [VBA-E][DEBUTANT] Agrandir une fenêtre classeur Excel
    Par skual dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 23/02/2006, 15h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo