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

FAQ Excel

FAQ ExcelConsultez toutes les FAQ

Nombre d'auteurs : 46, nombre de questions : 845, dernière mise à jour : 30 mars 2022 

 
OuvrirSommaireLes macros VBALes UserForm et les contrôlesLes UserForms

Consultez le tutoriel pour utiliser les UserForm pour en VBA Excel.

Créé le 9 avril 2007  par SilkyRoad

De nombreuses fonctions de l'API Win32, agissant sur les fenêtres, réclament en paramètre le handle (ou identificateur) de la dite fenêtre.
Malheureusement certains applicatifs tels Excel, Word... ne permettent pas de récupérer cette valeur.

la fonction FindWindowA, de l'API Win32, permet de connaître le handle d'une fenêtre à partir de son titre.

Vba
Sélectionnez
Private Declare Function FindWindowA Lib "user32" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
 
Private Sub UserForm_Initialize()
Dim MeHwnd As Long
    MeHwnd = FindWindowA(vbNullString, Me.Caption)
    MsgBox "le Handle de l'Userform " & Me.Caption & " est : 0x" & Hex(MeHwnd)
End Sub
Créé le 14 février 2004  par Bbil

Vous pouvez avoir besoin d'empêcher la fermeture d'une userform par la croix système.
2 solutions vous sont proposées ci-dessous :

1) La plus simple: inhiber l'action de la croix de fermeture dans l'évènement QueryClose de la UserForm :

Vba
Sélectionnez
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = vbFormControlMenu Then Cancel = True
End Sub

2) La plus jolie: masquer le bouton de fermeture de la UserForm :

Vba
Sélectionnez
'-- Dans la partie Déclaration de la Form :
Private Const SC_CLOSE = &HF060&
Private Const MF_BYCOMMAND = &H0&
 
Private Declare Function GetSystemMenu Lib "user32" _
        (ByVal hwnd As Long, ByVal bRevert As Long) As Long
 
Private Declare Function RemoveMenu Lib "user32" _
        (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
 
Private Declare Function FindWindowA Lib "user32" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
 
 
'-- Dans l'évènement Initialise de la Form :
Private Sub UserForm_Initialize()
Dim hSysMenu As Long
Dim MeHwnd As Long
    MeHwnd = FindWindowA(vbNullString, Me.Caption)
    If MeHwnd > 0 Then
        hSysMenu = GetSystemMenu(MeHwnd, False)
        RemoveMenu hSysMenu, SC_CLOSE, MF_BYCOMMAND
    Else
        MsgBox "Handle de " & Me.Caption & " Introuvable", vbCritical
    End If
End Sub
Créé le 14 février 2004  par Bbil, ThierryAIM

Il faut utiliser les fonctions de l'API Windows : SetWindowLong, SetWindowPos, GetWindowRect, GetWindowLong et hSysMenu et, pour le cas d'Excel ou Word qui ne donne pas accès au handle de la fenêtre : FindWindowA...

Déclarations à placer dans un module standard :

Vba
Sélectionnez
Public Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type
 
Const GWL_STYLE = (-16)
Const WS_CAPTION = &HC00000
Const SWP_FRAMECHANGED = &H20
 
Public Declare Function FindWindowA Lib "user32" _
        (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
 
Public Declare Function GetWindowRect Lib "user32" _
        (ByVal hwnd As Long, lpRect As RECT) As Long
 
Public Declare Function GetWindowLong Lib "user32" Alias _
        "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
 
Public Declare Function SetWindowLong Lib "user32" Alias _
        "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, _
        ByVal dwNewLong As Long) As Long
 
Public Declare Function SetWindowPos Lib "user32" _
        (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, _
        ByVal y As Long, ByVal cx As Long, ByVal cy As Long, _
        ByVal wFlags As Long) As Long

Fonction pour afficher ou masquer la barre de titre d'une UserForm (vous pouvez aussi la placer dans le module) :

Vba
Sélectionnez
Sub AfficheTitleBarre(stCaption As String, pbVisible As Boolean)
Dim vrWin As RECT
Dim style As Long
Dim lHwnd As Long
'- Recherche du handle de la fenêtre par son Caption
    lHwnd = FindWindowA(vbNullString, stCaption)
    If lHwnd = 0 Then
        MsgBox "Handle de " & stCaption & " Introuvable", vbCritical
        Exit Sub
    End If
 
    GetWindowRect lHwnd, vrWin
    style = GetWindowLong(lHwnd, GWL_STYLE)
    If pbVisible Then
        SetWindowLong lHwnd, GWL_STYLE, style Or WS_CAPTION
    Else
        SetWindowLong lHwnd, GWL_STYLE, style And Not WS_CAPTION
    End If
    SetWindowPos lHwnd, 0, vrWin.Left, vrWin.Top, vrWin.Right - vrWin.Left, _
            vrWin.Bottom - vrWin.Top, SWP_FRAMECHANGED
End Sub

Dans l'évènement Initialize de l'UserForm concernée :

Vba
Sélectionnez
Private Sub UserForm_Initialize()
'On passe en arguments : 
'    - le titre de la fenêtre
'    - False pour masquer la barre de titre 
    AfficheTitleBarre Me.Caption, False
End Sub
Créé le 14 février 2004  par Bbil

Cet exemple crée un UserForm et une ListBox par macro, ainsi qu'une macro évènementielle "Click()" pour la ListBox.

Vba
Sélectionnez
Option Explicit
Dim Usf As Object
 
Sub lancementProcedure()
Dim X As Object
Dim i As Integer
Dim strList As String
 
strList = "ListBox1"
Set X = creationUserForm_Et_listBox_Dynamique(strList)
 
For i = 1 To 10
    X.Controls(strList).AddItem "Donnee " & i
Next i
 
X.Show
 
ThisWorkbook.VBProject.VBComponents.Remove Usf
Set Usf = Nothing
End Sub
Vba
Sélectionnez
Function creationUserForm_Et_listBox_Dynamique(nomListe As String) As Object
Dim ObjListBox As Object
Dim j As Integer
 
  Set Usf = ThisWorkbook.VBProject.VBComponents.Add(3)
  With Usf
    .Properties("Caption") = "Mon UserForm"
    .Properties("Width") = 300
    .Properties("Height") = 200
  End With
 
Set ObjListBox = Usf.Designer.Controls.Add("Forms.ListBox.1")
 
With ObjListBox
    .Left = 20: .Top = 10: .Width = 90: .Height = 140
    .Name = nomListe
    .Object.ColumnCount = 1
    .Object.ColumnWidths = 70
End With
 
With Usf.CodeModule
    j = .CountOfLines
    .InsertLines j + 1, "Sub " & nomListe & "_Click()"
    .InsertLines j + 2, "If Not " & nomListe & ".ListIndex = -1 Then MsgBox " & nomListe
    .InsertLines j + 3, "End Sub"
End With
 
VBA.UserForms.Add (Usf.Name)
Set creationUserForm_Et_listBox_Dynamique = UserForms(UserForms.Count - 1)
End Function
Créé le 11 avril 2007  par SilkyRoad
Vba
Sélectionnez
Private Sub UserForm_Activate()
    With Me
        .StartUpPosition = 3
        .Width = Application.Width
        .Height = Application.Height
        .Left = 0
        .Top = 0
    End With
End Sub
Créé le 10 juin 2007  par SilkyRoad

Le contrôle Image ne permet pas d'afficher le type de fichier PNG.
Une solution consiste à visualiser l'image dans un contrôle WebBrowser.

Vba
Sélectionnez
Private Sub UserForm_Initialize()
    Dim S As String
    Dim Hauteur As Long, Largeur As Long
 
    Hauteur = WebBrowser1.Height
    Largeur = WebBrowser1.Width
    S = "C:\Dossier\LeChat.png"
 
    WebBrowser1.Navigate _
        "ABOUT:<HTML><HEAD><body><IMG WIDTH=" & Largeur & " HEIGHT=" & Hauteur & _
        " SRC='" & S & "'</IMG></BODY></HTML>"
End Sub
Créé le 10 juin 2007  par SilkyRoad

En utilisant la procédure suivante, un bouton de réduction est ajouté à côté de la croix de fermeture.
L'UserForm se réduira, en bas et à gauche de l'écran, lorsque vous cliquerez dessus.

Placez cette première macro dans un module standard. Vous utiliserez cette macro pour lancer l'UserForm.

Vba
Sélectionnez
Option Explicit
 
Sub LanceUSF()
    UserForm1.Show 0
End Sub

Ensuite, placez ce code dans le module objet du UserForm :

Vba
Sélectionnez
Option Explicit
 
Private Declare Function FindWindowA& Lib "User32" _
    (ByVal lpClassName$, ByVal lpWindowName$)
Private Declare Function EnableWindow& Lib "User32" _
    (ByVal hWnd&, ByVal bEnable&)
Private Declare Function GetWindowLongA& Lib "User32" _
    (ByVal hWnd&, ByVal nIndex&)
Private Declare Function SetWindowLongA& Lib "User32" _
    (ByVal hWnd&, ByVal nIndex&, ByVal dwNewLong&)
 
 
Private Sub UserForm_Initialize()
    Dim hWnd As Long
 
    hWnd = FindWindowA(vbNullString, Me.Caption)
    SetWindowLongA hWnd, -16, GetWindowLongA(hWnd, -16) Or &H20000
End Sub
 
 
Private Sub UserForm_Activate()
    Dim hWnd As Long
 
    hWnd = FindWindowA("XLMAIN", Application.Caption)
    EnableWindow hWnd, 1
End Sub
Créé le 20 août 2007  par SilkyRoad

Cet exemple permet de paramétrer un niveau de transparence (de 0 à 100%) dans un UserForm.

Téléchargez le classeur démo.

Créé le 20 août 2007  par Starec

Utilisez le mot clé New pour créer plusieurs instances d'une classe particulière. Votre UserForm peut ainsi être dupliqué plusieurs fois à l'écran.
Cet exemple est une traduction d'un article Microsoft.

Vba
Sélectionnez
'--- Dans un module standard --------
Option Explicit
Option Base 1
 
'Compte les instances d'UserForms.
Public mycount As Integer
'Tableau contenant les objets UserForm.
Public MyForms() As UserForm1
 
 
Sub New_UserForms()
    'Affiche l'UserForm.
    UserForm1.Show
End Sub
'-----------------------------------
Vba
Sélectionnez
'--- Dans un UserForm nommé UserForm1 -------
 
    'La forme doit contenir 3 CommandButton nommés :
        'cmdNewForm (caption = Nouveau)
        'cmdFormCaption  (caption = Affiche la propriété caption du UserForm)
        'cmdClose (caption = fermeture)
    'Une ListBox nommée :
        'ListBox1
 
Option Explicit
 
 
Private Sub cmdNewForm_Click()
    mycount = mycount + 1
 
    'Redéfinit la taille du tableau e , incrémentant d'une unité.
    ReDim Preserve MyForms(mycount)
 
    'Crée une nouvelle instance UserForm1.
    Set MyForms(mycount) = New UserForm1
 
    'Ajoute le numéro d'instance à la propriété 'Caption' du UserForm.
    MyForms(mycount).Caption = "instance " & mycount
 
    MyForms(mycount).cmdClose.Caption = "Masquer la forme"
 
    'Ajoute un élément dans la ListBox.
    UserForm1.ListBox1.AddItem mycount
End Sub
 
 
Private Sub cmdFormCaption_click()
    'Affiche la propriété 'Caption' du UserForm actif.
    MsgBox Me.Caption
End Sub
 
 
Private Sub cmdClose_Click()
    'Masque l'instance active.
    Me.Hide
End Sub
 
 
Private Sub ListBox1_MouseUp _
    (ByVal Button As Integer, ByVal Shift As Integer, _
    ByVal X As Single, ByVal Y As Single)
    'Affiche l'instance sélectionnée.
    MyForms(UserForm1.ListBox1.ListIndex + 1).Show
 
End Sub
 
 
Private Sub UserForm_QueryClose _
    (Cancel As Integer, CloseMode As Integer)
 
    'Gère l'absence de UserForm
     On Error Resume Next
 
     'Indiquez n'importe quelle valeur (Integer) autre que 0 pour désactiver
     'l'utilisation de la croix de fermeture ("X") du UserForm.
     Cancel = 1
 
End Sub
Créé le 2 octobre 2007  par Microsoft

Cet exemple suppose que l'UserForm contient un label nommé Label1. La barre d'outils s'affiche lorsque vous cliquez sur ce label.

Vba
Sélectionnez
Option Explicit
 
Dim X As Single
Dim Y As Single
 
 
'Création de la barre d'outils lors du lancement du UserForm
Private Sub UserForm_Initialize()
    Dim Barre As CommandBar
 
    Set Barre = CommandBars.Add("MenuUSF", msoBarPopup, False, True)
 
    With Barre.Controls.Add(msoControlButton, 1, , , True)
        .Caption = "Menu 01"
        .FaceId = 50
        'La procédure va appeler une macro nommée "Macro1", lorsque vous cliquerez
        'sur le bouton.
        .OnAction = "Macro1"
    End With
 
    With Barre.Controls.Add(msoControlButton, 2, , , True)
        .Caption = "Menu 02"
        .FaceId = 49
        'La procédure va appeler une macro nommée "Macro2", lorsque vous cliquerez
        'sur le bouton.
        .OnAction = "Macro2"
    End With
 
 
    With Me
        X = (.Width - .InsideWidth) / 2 + 8
        Y = .Height - .InsideHeight - X + 24
    End With
End Sub
 
 
 
'Affiche la barre d'outils lorsque vous cliquez sur le label.
Private Sub Label1_Click()
    Dim PosX As Single, PosY As Single
 
    PosX = (Me.Left + X + Label1.Left) * 4 / 3
    PosY = (Me.Top + Y + Label1.Top) * 4 / 3
 
    Application.CommandBars("MenuUSF").ShowPopup PosX, PosY
End Sub
 
 
 
'Supprime la barre d'outils lors de la fermeture du UserForm
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    On Error Resume Next
    CommandBars("MenuUSF").Delete
End Sub

Ajoutez ces deux macros dans un module standard :

Vba
Sélectionnez
Option Explicit
 
Sub Macro1()
    MsgBox "Essai 01"
End Sub
 
 
Sub Macro2()
    MsgBox "Essai 02"
End Sub
Créé le 5 décembre 2007  par SilkyRoad

L'icône va s'afficher dans l'angle supérieur gauche de la forme.

Vba
Sélectionnez
Option Explicit
 
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
      (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
 
Private Declare Function SendMessageA Lib "user32" _
      (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, _
      ByVal lParam As Long) As Long
 
Private Declare Function ExtractIconA Lib "shell32.dll" _
      (ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
 
 
 
Private Sub UserForm_Initialize()
    Dim Fichier As String
    Dim x As Long
 
    'Chemin et nom du fichier icône à afficher
    Fichier = "C:\Documents and Settings\mimi\dossier\bouton.ICO"
    'Vérifie si le fichier existe
    If Dir(Fichier) = "" Then Exit Sub
 
    x = ExtractIconA(0, Fichier, 0)
    SendMessageA FindWindow(vbNullString, Me.Caption), &H80, False, x
End Sub
Créé le 5 décembre 2007  par SilkyRoad

L'évènement Layout est déclenché lorsque vous changez la position du UserForm.

Cet exemple définit la position de la boîte de dialogue et empêche de le déplacer à l'écran.

Vba
Sélectionnez
Private Sub UserForm_Layout()
    Application.ScreenUpdating = False
    'Définit la position horizontale de l'USF
    Me.Left = 200
    'Définit la position verticale de l'USF
    Me.Top = 50
    Application.ScreenUpdating = True
End Sub
Créé le 19 février 2008  par SilkyRoad

Cette opération est réalisable en utilisant les API de Windows :
GetSysColor pour mémoriser la couleur initiale,
SetSysColors pour spécifier la nouvelle couleur.

Vba
Sélectionnez
Option Explicit
 
'Texte dans la barre de caption
Const COLOR_CAPTIONTEXT = 9
 
Private Declare Function GetSysColor Lib "user32" _
    (ByVal nIndex As Long) As Long
 
Private Declare Function SetSysColors Lib "user32" _
    (ByVal nChanges As Long, lpSysColor As Long, _
    lpColorValues As Long) As Long
 
 
Dim EnrCouleur As Long
 
 
'Modifie la couleur du texte lors del'affichage du UserForm
Private Sub UserForm_Activate()
    Me.Caption = "Mon texte perso"
 
    'Memorise la couleur initiale
    EnrCouleur = GetSysColor(COLOR_CAPTIONTEXT)
    'Modife la couleur
    SetSysColors 1, COLOR_CAPTIONTEXT, RGB(90, 0, 125)
 
End Sub
 
 
'Réinitialise la couleur
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    SetSysColors 1, COLOR_CAPTIONTEXT, EnrCouleur
End Sub
Créé le 20 septembre 2008  par SilkyRoad

Les fichiers .exd peuvent être à l'origine du problème. Ces fichiers sont généralement stockés dans le répertoire :
C:\Documents and Settings\nom_utilisateur\Application Data\Microsoft\Forms

Les fichiers EXD sont créés lorsque vous ajoutez des contrôles dans la boîte à outils et permettent d'accélérer le démarrage de vos classeurs par la mise en cache des informations du contrôle.

Si la boîte à outils reste vide, faites le ménage dans ce répertoire: Supprimez les fichiers EXD et BOX.

Les fichiers RefEdit.exd et EXCEL.box, qui sont utilisés pour les contrôles par défaut, seront recréés automatiquement lors de la réouverture de l'application. Il vous restera ensuite à ajouter les autres contrôles manuellement (Clic droit sur la boîte de dialogue / contrôles supplémentaires).

Créé le 18 novembre 2008  par SilkyRoad

Il est parfois utile de lister les noms des contrôles et leur contenu lorsque que vous travaillez sur des projets volumineux.
Cette procédure montre comment boucler sur les userforms du classeur, puis sur tous les contrôles afin d'identifier les labels.

Nécessite d'activer la référence Microsoft Visual Basic for Applications Extensibility 5.3.

Vba
Sélectionnez
Dim VBCmp As VBComponent
Dim Ctrl As Control
 
'Boucle sur les composants du classeur
For Each VBCmp In ThisWorkbook.VBProject.VBComponents
    'S'il s'agit d'un UserForm
    If VBCmp.Type = 3 Then
        Debug.Print VBCmp.Name
        'Boucle sur les contrôles des userforms
        For Each Ctrl In VBCmp.Designer.Controls
        'S'il s'agit d'un label
        If TypeName(Ctrl) = "Label" Then _
            Debug.Print Ctrl.Name & " / " & Ctrl.Caption
        Next Ctrl
 
        Debug.Print "-----"
    End If
 
Next VBCmp
Créé le 18 novembre 2008  par SilkyRoad

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2009 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.