触发通过类输入控件的字段行为

时间:2018-08-20 12:13:56

标签: excel excel-vba

我在星期五(here is the query)上提出了一个查询,根据David Zemens的说明和BrakNicku的说明,该查询非常有效。我遇到的问题是:我要使用的事件之一是 Enter 。不幸的是,在课堂上,我没有这个活动的选择。是否有人知道是否可以将其添加到类中或以某种方式触发控件的 Enter 事件?

我尝试使用该类中可用的大多数事件,但是它们都没有按照我需要的方式运行。简要介绍一下背景:我使用 Enter 事件为 focus 中的字段设置帮助文本。因此,每次用户输入字段时,我都有一个帮助文本框,其中填充了帮助文本

很遗憾,我无法共享该工作簿,但很高兴回答任何问题

预先感谢

3 个答案:

答案 0 :(得分:1)

假设您的用户表单( Userform1 )如下

enter image description here

我将演示2个控件的Enter EventTextBoxComboBox

确保将CommandButton1首先放在用户表单上。或者,将其TabIndex设置为0。这样一来,在加载用户窗体时,命令按钮将首先成为焦点,并且您可以测试EnteringTextBox中的ComboBox

enter image description here

将此内容粘贴到类模块中。我的班级模块名称为Class1

Option Explicit

Public WithEvents Usrfrm As UserForm1
Const MyMsg As String = "Hiya there. Did you just try to sneak into the "

Private Sub Usrfrm_OnEnter(ctrl As msforms.Control)
    Select Case True
        Case TypeName(ctrl) Like "ComboBox"
            'Call Usrfrm.Combobox_List(ctrl)
            MsgBox MyMsg & "combobox?", vbCritical, "Aha!"
        Case TypeName(ctrl) Like "TextBox"
            MsgBox MyMsg & "textbox?", vbCritical, "Aha!"
    End Select
End Sub

将其粘贴到用户表单代码区域

Option Explicit

Public Event OnEnter(ctrl As msforms.Control)
Private prevCtl As msforms.Control
Private mycls As Class1
Private IsfrmUnloaded As Boolean

Private Sub CommandButton1_Click()
    Unload Me
End Sub

Private Sub UserForm_Layout()
    Call spyWhatsGoingOn
End Sub

Private Sub spyWhatsGoingOn()
    Set mycls = New Class1
    Set mycls.Usrfrm = Me

    IsfrmUnloaded = False

    Set prevCtl = Me.ActiveControl

    RaiseEvent OnEnter(Me.ActiveControl)

    Do While IsfrmUnloaded = False
        If Not prevCtl Is Nothing Then
            If Not prevCtl Is Me.ActiveControl Then
                RaiseEvent OnEnter(Me.ActiveControl)
                Me.ActiveControl.SetFocus
            End If
        End If
        Set prevCtl = Me.ActiveControl
        DoEvents
    Loop
End Sub

演示

enter image description here

答案 1 :(得分:0)

这是另一种解决方案,(不适用于MAC)

打开记事本并复制下面的代码,并将其粘贴到新的txt文件中 保存它CatchEvents.cls

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "CatchEvents"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private Type GUID
      Data1 As Long
      Data2 As Integer
      Data3 As Integer
      Data4(0 To 7) As Byte
End Type

#If VBA7 And Win64 Then
      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
#Else
     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
#End If

Private EventGuide As GUID
Private Ck As Long
Private ctl As Object
'All Other Control-Events also possible
Public Sub MyEnter()
Attribute MyEnter.VB_UserMemId = -2147384830
  Select Case TypeName(ctl)
  Case "TextBox": MsgBox "Your code for " & ctl.Name & " here!"
  Case Else: MsgBox "You entered no TextBox but another control (" & ctl.Name & ")!"
  End Select
End Sub

Public Sub ConnectAllEvents(ByVal Connect As Boolean)
      With EventGuide
          .Data1 = &H20400
          .Data4(0) = &HC0
          .Data4(7) = &H46
      End With
      ConnectToConnectionPoint Me, EventGuide, Connect, ctl, Ck, 0&
End Sub

Public Property Let Item(Ctrl As Object)
      Set ctl = Ctrl
      Call ConnectAllEvents(True)
End Property

Public Sub Clear()
      If (Ck <> 0) Then Call ConnectAllEvents(False)
      Set ctl = Nothing
End Sub

在VBA编辑器中,您导入此文件

在用户窗体代码中添加:(当您已经有一个初始化事件时,将它们组合起来)

Private AllControls() As New CatchEvents 'on top

Private Sub UserForm_Initialize()
ReDim AllControls(Controls.Count - 1)
    For j = 0 To Controls.Count - 1
        AllControls(j).Item = Controls(j)
    Next
End Sub

现在将捕获任何控件的每个Enter事件,因此您必须采取相应的措施。 可以通过这种方式捕获用户窗体上的每个事件。

答案 2 :(得分:0)

所以我采用的方法是:我已经具有捕获Change事件(can be seen here)的类模块。由于我无法访问课堂上的Enter事件,因此我在此类中使用了KeyUpMouseDown事件来为每个控件设置帮助。通过这种方式,用户可以通过单击或选择选项卡进入该字段:显示所选控件的帮助