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

VBA Discussion :

Interception des évènements Enter et Exit des contrôles MSForms.TextBox


Sujet :

VBA

  1. #1
    Membre éprouvé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    Février 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Février 2004
    Messages : 897
    Points : 1 061
    Points
    1 061
    Par défaut Interception des évènements Enter et Exit des contrôles MSForms.TextBox
    Bonjour,

    J'ai récupéré en parti le code suivant sur le Web que j'essaye d'adapter afin d'intercepter les évènements Enter et Exit générés par les contrôles MSForms.TextBox.

    J'ai le formulaire qui se charge et se referme convenablement, me semble-t-il. Ce qui me laisse à penser ne pas avoir de problèmes particuliers de ce côté.

    Par contre mon problème est que je n'arrive pas à trapper les évènements Enter et Exit, malgré le fait que le code provienne d'un exemple qui lui fonctionne très bien (voir en pièce attachée).

    La méthode Initialize du formulaire fait appel au module de classe ci-dessous pour la gestion des évènements.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
     
    Option Explicit
     
    Private Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(0 To 7) As Byte
    End Type
     
    #If VBA7 Then
        Private Declare PtrSafe Function IIDFromString Lib "ole32.dll" (ByVal lpsz As LongPtr, lpiid As GUID) As Long
        Private Declare PtrSafe Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As LongPtr) As Long
        Private Declare PtrSafe Function IsWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long
     
        Private hwnd As LongPtr
     
    #Else
        Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, lpiid As GUID) As Long
        Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As Long) As Long
        Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
        Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As Long) As Long
     
        Private hwnd As Long
     
    #End If
     
    Private WithEvents CmndBras  As CommandBars
     
    Private oClientForm As Object
    Private oCurrentTextBox As MSForms.TextBox
    Private sClassInstanceName As String
     
    Event OnEnter(ByVal TextBox As MSForms.TextBox)
    Event OnExit(ByVal TextBox As MSForms.TextBox, ByRef Cancel As MSForms.ReturnBoolean)
    Event BeforeUpdate(ByVal TextBox As MSForms.TextBox, ByRef Cancel As MSForms.ReturnBoolean)
    Event AfterUpdate(ByVal TextBox As MSForms.TextBox)
     
     
    ' __________________________________ CLASS PUBLIC METHOD ________________________________________
     
    Property Let HookEvents(ClassInstanceName As String, Optional ByVal TextBox As MSForms.TextBox, ByVal SetEvents As Boolean)
     
        Const S_OK = &H0
        Static lCookie As Long
        Dim tIID As GUID
     
        Debug.Print "HookEvents"
        If Not TextBox Is Nothing Then
            Debug.Print "HookEvents : Not TextBox Is Nothing"
            Set oCurrentTextBox = TextBox
            Debug.Print "HookEvents oCurrentTextBox = TextBox : " & oCurrentTextBox.Name
            Set oClientForm = GetUserForm(TextBox)
            sClassInstanceName = ClassInstanceName
            Debug.Print "HookEvents sClassInstanceName = ClassInstanceName : " & sClassInstanceName
     
            Set CmndBras = Application.CommandBars
            Call IUnknown_GetWindow(oClientForm, VarPtr(hwnd))
        End If
        If IIDFromString(StrPtr("{00020400-0000-0000-C000-000000000046}"), tIID) = S_OK Then
            If ConnectToConnectionPoint(Me, tIID, SetEvents, TextBox, lCookie) = S_OK Then
                Debug.Print oCurrentTextBox.Name & IIf(SetEvents, " connected", " disconnected") & " successfully"
            Else
                Debug.Print "Connection failed for: " & oCurrentTextBox.Name
            End If
        Else
            Debug.Print "HookEvents IIDFromString(StrPtr(""{00020400-0000-0000-C000-000000000046}""), tIID) = S_OK : False"
        End If
     
    End Property
     
    ' __________________________________ TEXTBOX CONTROL EVENTS ________________________________________
     
    Public Sub OnEnter()
        ' Attribute OnEnter.VB_UserMemId = &H80018202
        Dim oThis As ClassTextBoxEvents
        Set oThis = Me
        Call CallByName(oClientForm, sClassInstanceName, VbSet, oThis)
        Set oThis = Nothing
        Debug.Print "OnEnter oCurrentTextBox : " & oCurrentTextBox.Name
        RaiseEvent OnEnter(oCurrentTextBox)
    End Sub
     
    Public Sub OnExit(ByVal Cancel As MSForms.ReturnBoolean)
        ' Attribute OnExit.VB_UserMemId = &H80018203
        Debug.Print "OnExit oCurrentTextBox : " & oCurrentTextBox.Name
        RaiseEvent OnExit(oCurrentTextBox, Cancel)
    End Sub
     
    Public Sub BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
        ' Attribute BeforeUpdate.VB_UserMemId = &H80018201
        RaiseEvent BeforeUpdate(oCurrentTextBox, Cancel)
    End Sub
     
    Public Sub AfterUpdate()
        ' Attribute AfterUpdate.VB_UserMemId = &H80018200
        RaiseEvent AfterUpdate(oCurrentTextBox)
    End Sub
     
     
    ' __________________________________ PRIVATE ROUTINES ________________________________________
     
    Private Function GetUserForm(ByVal Ctrl As MSForms.Control) As Object
        Dim oTmp As Object
        Debug.Print "GetUserForm"
        Set oTmp = Ctrl.Parent
        Do While TypeOf oTmp Is MSForms.Control
            Set oTmp = oTmp.Parent
            Debug.Print "GetUserForm oTmp = oTmp.Parent : " & oTmp.Name
        Loop
        Set GetUserForm = oTmp
    End Function
     
    Private Sub CmndBras_OnUpdate()
        Debug.Print "CmndBras_OnUpdate"
        If IsWindow(hwnd) = 0 Then
            Debug.Print "CmndBras_OnUpdate IsWindow(hwnd) = 0 : " & IsWindow(hwnd)
            HookEvents(sClassInstanceName, oCurrentTextBox) = False
        End If
    End Sub
     
    Private Sub Class_Terminate()
        Debug.Print "Class instance treminated and memory released properly related to: " & oCurrentTextBox.Name
        Set oCurrentTextBox = Nothing
        Set oClientForm = Nothing
        Set CmndBras = Nothing
    End Sub

    Ci-dessous, la classe du formulaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    Option Compare Database
    Option Explicit
     
    Private WithEvents tbx As ClassTextBoxEvents
     
    Private Sub UserForm_Initialize()
     
        Debug.Print "UserForm_Initialize FrmTabularEmployes"
     
        Dim frm As UserForm_FrmTabularEmployes
        Set frm = Me
     
        frm.Caption = "frm is an instance object of the UserForm_FrmTabularEmployes Class"
        Debug.Print "frm.Name : " & frm.Name
     
        Dim obj As Object
        Dim ctl As MSForms.Control
        Dim fld As MSForms.TextBox
     
        Dim lgNbreLignes As Long
        Dim intHeightLigne As Integer
        Dim intTopLeft As Integer
     
        lgNbreLignes = 4
        intHeightLigne = 20
        intTopLeft = 10
     
        Dim i As Long
        Dim j As Long
     
        j = 20
     
        For i = 0 To lgNbreLignes
            Set fld = frm.Controls.Add("Forms.TextBox.1", "fldTest" & i, True)
            j = j + intHeightLigne
            fld.Top = j
            fld.Left = intTopLeft
            fld.tag = i
            fld.Value = "fldTest" & i
        Next
     
        For Each ctl In frm.Controls
            If TypeOf ctl Is MSForms.TextBox Then
                Set tbx = New ClassTextBoxEvents
                tbx.HookEvents(ClassInstanceName:="tbx", TextBox:=ctl) = True
            End If
        Next ctl
     
        frm.ScrollBars = fmScrollBarsVertical
        frm.KeepScrollBarsVisible = fmScrollBarsNone
        frm.ScrollHeight = intHeightLigne * (lgNbreLignes + 3)
     
        With frm.Controls
            For i = 0 To .Count - 1
                If TypeName(.Item(i)) = "TextBox" Then
                    Debug.Print "frm.Controls.Item(" & i & ") : " & TypeName(.Item(i)); " " & VarType(.Item(i)) & " - Tag " & .Item(i).tag & " - Name " & .Item(i).Name & " - Value " & .Item(i).Value
                End If
            Next
        End With
     
        Debug.Print "Trace"
     
    End Sub
     
    Private Sub tbx_Change()
        Debug.Print "tbx_Change FrmTabularEmployes"
    End Sub
     
    Private Sub tbx_OnEnter(ByVal TextBox As MSForms.TextBox)
        Debug.Print "tbx_OnEnter FrmTabularEmployes"
    End Sub
     
    Private Sub tbx_OnExit(ByVal TextBox As MSForms.TextBox, Cancel As MSForms.ReturnBoolean)
     
        Debug.Print "tbx_OnExit FrmTabularEmployes"
     
        Debug.Print "ActiveControl : " & Me.ActiveControl.Name
        Debug.Print "UserForm_FrmTabularEmployes!fldTest1.Name : " & UserForm_FrmTabularEmployes!fldTest1.Name
     
        Dim tag As Long
        tag = Me.ActiveControl.tag + 1
     
        Debug.Print "tag : " & tag
        Debug.Print "Me.Controls.Item(" & tag & ").Name : " & Me.Controls.Item(tag).Name
        Me.Controls.Item(tag).SetFocus
     
    End Sub
     
    Private Sub tbx_BeforeUpdate(ByVal TextBox As MSForms.TextBox, Cancel As MSForms.ReturnBoolean)
        Debug.Print "tbx_OnEnter FrmTabularEmployes"
    End Sub
     
    Private Sub tbx_AfterUpdate(ByVal TextBox As MSForms.TextBox)
        Debug.Print "tbx_AfterUpdate FrmTabularEmployes"
    End Sub
    Vos contributions m'aideraient à comprendre pourquoi ce code ne fonctionne pas comme escompter.
    Merci d'avance
    .
    Pièce jointe 656542
    Diviser c'est régner : United we stand, Divided we fall
    .

  2. #2
    Invité
    Invité(e)
    Par défaut
    Le module du class contient des propriétés internes pour attacher les fonctions à l'interface qui gère l'evenement , il doit être importé et pas juste copier le code .

    deuxième note redéclarer le variable tbx comme public
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Private WithEvents tbx As ClassTextBoxEvents

  3. #3
    Membre éprouvé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    Février 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Février 2004
    Messages : 897
    Points : 1 061
    Points
    1 061
    Par défaut
    Bonjour Volid,
    Merci de ta réponse.
    Tu précises
    Le module de class contient des propriétés internes pour attacher les fonctions à l'interface qui gère l'évènement, il doit être importé et pas juste copier le code.
    Peux-tu me préciser ce qui doit être importé au juste ?
    Est-ce le module de classe ou plutôt l'interface qui gère l'évènement ?
    Merci d'avance
    .
    Diviser c'est régner : United we stand, Divided we fall
    .

  4. #4
    Invité
    Invité(e)
    Par défaut
    A partir du fichier Excel qui fonctionne exporter le module de classe et enregistrez le dans un fichier et après dans votre nouveau projet importer le fichier ( les deux opérations sont possible via le menu principale ou contextuel)

    malheureusement y a pas moyens pour définir les DispID des méthodes directement dans l'éditeur VBA
    Attribute OnEnter.VB_UserMemId = -2147384830
    Attribute OnExit.VB_UserMemId = -2147384829

    Le fichier exporté "CTextBoxEvents.cls" donne le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
    END
    Attribute VB_Name = "CTextBoxEvents"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = False
    Option Explicit
     
    Private Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(0 To 7) As Byte
    End Type
     
    #If VBA7 Then
        Private Declare PtrSafe Function IIDFromString Lib "ole32.dll" (ByVal lpsz As LongPtr, lpiid As GUID) As Long
        Private Declare PtrSafe Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As LongPtr) As Long
        Private Declare PtrSafe Function IsWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
        Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long
     
        Private hwnd As LongPtr
     
    #Else
        Private Declare Function IIDFromString Lib "ole32.dll" (ByVal lpsz As Long, lpiid As GUID) As Long
        Private Declare Function ConnectToConnectionPoint Lib "shlwapi" Alias "#168" (ByVal punk As stdole.IUnknown, ByRef riidEvent As GUID, ByVal fConnect As Long, ByVal punkTarget As stdole.IUnknown, ByRef pdwCookie As Long, Optional ByVal ppcpOut As Long) As Long
        Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
        Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As Long) As Long
     
        Private hwnd As Long
     
    #End If
     
    Private WithEvents CmndBras  As CommandBars
    Attribute CmndBras.VB_VarHelpID = -1
     
    Private oClientForm As Object
    Private oCurrentTextBox As MSForms.TextBox
    Private sClassInstanceName As String
     
    Event OnEnter(ByVal TextBox As MSForms.TextBox)
    Event OnExit(ByVal TextBox As MSForms.TextBox, ByRef Cancel As MSForms.ReturnBoolean)
    Event BeforeUpdate(ByVal TextBox As MSForms.TextBox, ByRef Cancel As MSForms.ReturnBoolean)
    Event AfterUpdate(ByVal TextBox As MSForms.TextBox)
     
     
    ' __________________________________ CLASS PUBLIC METHOD ________________________________________
     
    Public Property Let HookEvents(ClassInstanceName As String, Optional ByVal TextBox As MSForms.TextBox, ByVal SetEvents As Boolean)
     
        Const S_OK = &H0
        Static lCookie As Long
        Dim tIID As GUID
     
        If Not TextBox Is Nothing Then
            Set oCurrentTextBox = TextBox
            Set oClientForm = GetUserForm(TextBox)
            sClassInstanceName = ClassInstanceName
     
            Set CmndBras = Application.CommandBars
            Call IUnknown_GetWindow(oClientForm, VarPtr(hwnd))
        End If
        If IIDFromString(StrPtr("{00020400-0000-0000-C000-000000000046}"), tIID) = S_OK Then
            If ConnectToConnectionPoint(Me, tIID, SetEvents, TextBox, lCookie) = S_OK Then
                'Debug.Print oCurrentTextBox.Name & IIf(SetEvents, " connected ", " disconnected") & " successfully."
            Else
                'Debug.Print "Connection failed for: " & oCurrentTextBox.Name
            End If
        End If
     
    End Property
     
    ' __________________________________ TEXTBOX CONTROL EVENTS ________________________________________
     
    Public Sub OnEnter() 
    Attribute OnEnter.VB_UserMemId = -2147384830
        'Attribute OnEnter.VB_UserMemId = &H80018202
        Dim oThis As CTextBoxEvents
        Set oThis = Me
        Call CallByName(oClientForm, sClassInstanceName, VbSet, oThis)
        Set oThis = Nothing
        RaiseEvent OnEnter(oCurrentTextBox)
    End Sub
     
    Public Sub OnExit(ByVal Cancel As MSForms.ReturnBoolean)
    Attribute OnExit.VB_UserMemId = -2147384829
        'Attribute OnExit.VB_UserMemId = &H80018203
        RaiseEvent OnExit(oCurrentTextBox, Cancel)
    End Sub
     
    Public Sub BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    Attribute BeforeUpdate.VB_UserMemId = -2147384831
        'Attribute BeforeUpdate.VB_UserMemId = &H80018201
        RaiseEvent BeforeUpdate(oCurrentTextBox, Cancel)
    End Sub
     
    Public Sub AfterUpdate()
    Attribute AfterUpdate.VB_UserMemId = -2147384832
        'Attribute AfterUpdate.VB_UserMemId = &H80018200
        RaiseEvent AfterUpdate(oCurrentTextBox)
    End Sub
     
     
    ' __________________________________ PRIVATE ROUTINES ________________________________________
     
    Private Function GetUserForm(ByVal Ctrl As MSForms.Control) As Object
        Dim oTmp As Object
        Set oTmp = Ctrl.Parent
        Do While TypeOf oTmp Is MSForms.Control
            Set oTmp = oTmp.Parent
        Loop
        Set GetUserForm = oTmp
    End Function
     
    Private Sub CmndBras_OnUpdate()
        If IsWindow(hwnd) = 0 Then
            HookEvents(sClassInstanceName, oCurrentTextBox) = False
        End If
    End Sub
     
    Private Sub Class_Terminate()
        'Debug.Print "Class instance treminated and memory released properly related to: " & oCurrentTextBox.Name
        Set oCurrentTextBox = Nothing:  Set oClientForm = Nothing:  Set CmndBras = Nothing
    End Sub

  5. #5
    Membre éprouvé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    Février 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Février 2004
    Messages : 897
    Points : 1 061
    Points
    1 061
    Par défaut
    Merci Volid
    Après application de tes indications, cela fonctionne parfaitement maintenant
    Encore merci
    .
    Diviser c'est régner : United we stand, Divided we fall
    .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 27/06/2024, 11h53
  2. Interception des erreurs sur un dbnavigator
    Par Jeepy dans le forum Bases de données
    Réponses: 1
    Dernier message: 16/05/2005, 16h59
  3. Interception des messages CLAVIER
    Par dede92 dans le forum Windows
    Réponses: 10
    Dernier message: 03/03/2005, 17h47
  4. Interception des commandes in et out
    Par KDD dans le forum x86 16-bits
    Réponses: 13
    Dernier message: 18/12/2002, 16h55
  5. [VB6] Interception des évènement Copier/Couper/Coller
    Par youtch dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 18/10/2002, 17h09

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