Icône de la ressource

VBA - MsgBox personnalisé - MsgBoxPerso avec 0 à 12 boutons (type MsgBox ou textuels), icône & timer V20

Le fichier à télécharger contient:
  1. Le UserForm MsgBoxPerso à importer dans le projet VBA pour utiliser ce MsgBox Personnalisé,
  2. Le Module_Test qui donne quelques exemples d'utilisation.
L'appel de la fonction:
VB:
Dim Retour As Variant
'
Retour = MsgBoxPerso.Display(...voir la description des paramètres dans le code...)

Les principales caractéristiques:
  • Office 2010+ (VBA7 sinon modifier les déclarations API comme indiqué).
  • Peut être utilisé exactement comme un MsgBox pour ses constantes de boutons de 0 à 768 (sauf paramètres helpfile & context) et pour ses constantes de retour.
  • Peut utiliser jusqu'à 12 boutons en format texte libre.
  • Peut être prépositionné (valeurs Left et Top en paramètres d'appel).
  • Peut être repositionné par une fonction utilisateur (ReposFunction en paramètre d'appel) après qu'il a pris ses dimensions définitives juste avant son affichage (voir aussi cette ressource pour le positionnement d'un UserForm sur un Objet).
  • Inclut un Timer pour limiter le temps d'affichage si besoin avec sa valeur de retour dédiée (-1).
  • Grâce à son paramètre ShowMode, permet d'afficher le message de manière NON modale.
  • Grâce à son paramètre ShowOnAllWindows, permet d'afficher le message sur tous les classeurs.
    Limitation: le coin bas droit du UserForm doit être dans la fenêtre Excel. S'il ce n'est pas le cas, le UserForm sera automatiquement repositionné pour que ce soit le cas.
    Techniquement, cette limitation est due au fait que, pour conserver l'affichage sur toutes les fenêtres Excel, le code définit la fenêtre Excel active comme Parent du UserForm ce qui en limite l'affichage à cette même fenêtre Excel et en modifie l'aspect des bordures sur les versions "récentes" d'Excel.

    Cette méthode du Parent s'est imposée plutôt que la re-création du UserForm (Unload + Show) sur la nouvelle fenêtre Excel qui nécessiterait un module dédié pour le déclenchement asynchrone (Application.OnTime Now Module.Fonction) du ré-affichage (Show) qui ne peut hélas pas se faire dans le code du UserForm après sa fermeture (Unload), les fonctions même publiques du UserForm ne pouvant être référencées en Application.OnTime Now ou même en fonction Timer.
Remarques:
  • Restriction: Si la fonction MsgBoxPerso.Display() est appelée d'un UserForm affiché en mode vbModal, le Timer, l'affichage du menu système (minimisation) et l'affichage sur toutes les fenêtres Excel ne sont pas disponibles.
    En effet, ces fonctionnalités ne sont disponibles que si le UserForm MsgBoxPerso est affiché en mode vbModeless et Excel l'interdit à partir d'un UserForm Modal.
Versions:
  • V1 - Initiale
  • V2 - Le paramètre ShowMode (vbModal ou vbModeless pas défaut) permet maintenant d'utiliser la fonction MsgBoxPerso.Display() dans un UserForm lui-même Modal. En effet, un UserForm Modal n'accepte pas qu'on affiche un UserForm non Modal "au-dessus" de lui (erreur 401).
    Cependant, avec ShowMode = vbModal, on perd le Timer.
  • V3 - Corrections pour compatibilité Office 64 bits
  • V4 - Activation de la fenêtre appelante en retour de fonction (utile si l'appel est fait dans un UserForm vbModeless).
  • V5 - Supprime le paramètre ShowMode et gère l'erreur 401 pour passer automatiquement en vbModal si la fonction est appelée par un UserForm vbModal, mode dans lequel on perd le Timer.
  • V6 - Correction d'un Bug introduit par la V5 sur les retours en Caption des boutons (quand le paramètre ReturnButtonNumber:=False).
  • V7 - Appel de la fonction utilisateur de positionnement dans l'Activate() plutôt qu'avant le Show() pour avoir la forme définitive du UserForm (avec ou sans Caption).
  • V8 - Protection appel réccurrent et mise en ForeGround si appel d'un UserForm non modal.
    Remplacement des évènements MouseDown() par MouseUp() pour ne pas interférer sur l'appelant lors du MouseUp().
  • V9 - Ajout du paramètre ShowOnAllWindows pour garder le message affiché sur toutes les fenêtres Excel.
  • V10 - Correction problème retour sur classeur initial avec le paramètre ShowOnAllWindows.
  • V11 - Gestion de CTL + Pause pour arrêter le code en mode debug.
  • V12 - Ajout du paramètre SystemMenu qui permet la minimisation du UserForm au milieu-bas de la fenêtre Excel.
  • V13 - Améliorations de mode ShowOnAllWindows et correction centrage par défaut en multi-moniteurs.
  • V14 - Pour éviter des petits problèmes d'affichage du message lancé à partir d'un UserForm affiché vbModeless, le paramètre Interactive a été remplacé par le paramètre ShowMode.
  • V15 - Comportement multi-classeurs (paramètre ShowOnAllWindows) amélioré sur des fenêtres Excel non forcément plein écran.
  • V16 - Micro-correction pour un calcul 100% précis des coordonnées de la fenêtre Excel (fonction GetExcelClientWindowRECT() ajoutée) qui prend des valeurs Left et Top négatives incompréhensibles en plein écran au lieu de (0, 0).
  • V17 - Correction d'un bug en affichage à partir d'un UserForm vbModeless qui figeait le message lorsqu'on cliquait sur le UserForm appelant.
    Accessoirement, un indicateur Public (MsgBoxPerso.CurrentlyDisplayedModeless) permet de savoir qu'un MsgBoxPerso Modeless est en cours d'affichage pour que le UserForm appelant (forcément Modeless, voir Restriction) évite de se placer en premier plan avec un SetForegroundWindow() (surtout sur un évènement UserForm_MouseMove comme dans cette Ressource) qui entrerait alors en conflit avec celui du MsgBoxPerso qui utilise cette même fonction API pour être sûr de rester lui-même au premier plan et ne pas être masqué par le UserForm appelant.
  • V18 - Après traitement, réactive un UserForm appelant affiché en vbModeless et réactive le curseur sur l'ActiveControl TextBox ou ComboBox de ce UserForm appelant.
    V18b - Ajout d'un commentaire pour indiquer l'adresse de cette Ressource.
  • V19 - Correction pour permettre, dans la position initiale, de préciser indépendamment le PosLeft ou le PosTop.
  • V20 - Ajout du paramètre UserButtonFunction qui est une fonction utilisateur appelée 3 fois pas seconde pouvant renvoyer un bouton (voir exemple avec le bouton de test Message à fermeture conditionnelle).
Démo.gif


Une fonctionnalité intéressante:
Il est possible d'afficher le message en mode vbModeless, c'est à dire de pouvoir interagir avec la feuille ou le classeur pendant que le message est affiché.
Ainsi un prompt MsgBoxPerso.Display peut être utilisé pour demander à l'utilisateur de réaliser certaines actions à l'issue desquelles il fermera le prompt indiquant au code qu'il peut en exploiter le résultat.

Un exemple avec ce code:
VB:
Sub Test()
    Dim CB As OLEObject
    Dim Réponse As Variant
    Dim S As String
 
    'RAZ des CheckBoxes
    For Each CB In ActiveSheet.OLEObjects
        CB.Object.Value = False
    Next CB
 
    '-----------------
    'Prompt vbModeless
    '-----------------
    Réponse = MsgBoxPerso.Display("Sélectionner les périodes du jour à prendre en compte." & vbCrLf & vbCrLf & _
                                   "Après avoir terminé la sélection, cliquer [Valider]", _
                                   Buttons:="Valider|Abandonner", _
                                   Title:="Périodes du jour", _
                                   ShowMode:=vbModeless)
    'Abandon
    If Réponse = 2 Then
        MsgBoxPerso.Display "Abandon"
        Exit Sub
    End If
 
    'Affichage de la sélection
    S = "Sélection:" & vbCrLf
 
    For Each CB In ActiveSheet.OLEObjects
        'Le nom de CheckBoxes est "CheckBox" + leur Caption
        If CB.Object.Value Then S = S & "- " & Mid(CB.Name, Len("CheckBox") + 1) & vbCrLf
    Next CB
 
    MsgBoxPerso.Display S
End Sub
MsgBoxPersoModeless.gif

Une autre fonctionnalité intéressante:
Il est possible de garder affiché le message sur plusieurs classeurs en utilisant le paramètre ShowOnAllWindows valorisé à True.

Cela peut être utilisé par exemple pour demander à l'utilisateur de choisir un classeur (et une feuille) pour lui appliquer un traitement:
  1. Afficher le message avec ShowOnAllWindows:=True en demandant à l'utilisateur de choisir le classeur/feuille.
  2. L'utilisateur peut alors ouvrir et/ou sélectionner le classeur/feuille concerné.
    Le message restera présent sur le(s) classeur(s) activé(s).
  3. Lorsque l'utilisateur aura cliqué sur un bouton donné, appliquer le traitement sur le classeur/feuille actif.
1679233844133.gif


Une autre fonctionnalité intéressante:
Il est possible de conditionner la fermeture du message à des actions de l'utilisateur en utilisant le paramètre UserButtonFunction qui indique le nom d'une fonction dont le rôle est de vérifier les conditions requises, et si elles sont remplies, de retourner une valeur de bouton (vbOk, vbCancel, etc...) qui sera utilisée comme une valeur de bouton cliqué (voir Sub Test9 dans le classeur).

MsgCond.gif