Excel VBA按钮事件处理程序实现

Excel VBA按钮事件处理程序实现,excel,vba,Excel,Vba,我想使用以下类代码在类中处理单击命令按钮的操作 Option Explicit Private m_First As MSForms.CommandButton Private WithEvents evFirst As MSForms.CommandButton Property Get First() As MSForms.CommandButton Set First = m_First End Property Pro

我想使用以下类代码在类中处理单击命令按钮的操作

Option Explicit

Private m_First                     As MSForms.CommandButton
Private WithEvents evFirst          As MSForms.CommandButton

Property Get First() As MSForms.CommandButton
    Set First = m_First
End Property
Property Let First(ByRef o As MSForms.CommandButton)
    Set m_First = o
    Set evFirst = o
End Property

Private Sub evFirst_Click()
    MsgBox "It Worked!"
End Sub
除此之外,我还想知道为什么表单中的按钮引用与课堂中的按钮引用不同,即:

Sub Tester()
    Dim f As New UserForm1
    Dim o As New cButtonClass
    o.First = f.CommandButton1

    Dim k1 As LongLong: k1 = ObjPtr(o.First)
    Dim k2 As LongLong: k2 = ObjPtr(f.CommandButton1)
    Debug.Assert k1 = k2 'NOPE!
End Sub

为什么这样不行?修复方法是什么?

这里是反映上述注释的更新代码。它按预期工作。然而,对于您关于
ObjPtr
的另一个问题,我还没有答案

以下是课程代码:

Option Explicit

Private WithEvents evFirst As MSForms.CommandButton

Property Get First() As MSForms.CommandButton
    Set First = evFirst
End Property

Property Set First(ByRef o As MSForms.CommandButton)
    Set evFirst = o
End Property

Private Sub evFirst_Click()
    MsgBox "Class Click"
End Sub
以下是工作表代码:

Option Explicit

Public Sub Tester()
    Dim f As UserForm1
    Dim o As cButtonClass

    Set f = New UserForm1
    Set o = New cButtonClass
    Set o.First = f.CommandButton1
    f.Show vbModal

    Dim k1 As LongPtr: k1 = ObjPtr(o.First)
    Dim k2 As LongPtr: k2 = ObjPtr(f.CommandButton1)
    Debug.Assert k1 = k2 'NOPE!
End Sub
以下是用户表单代码:

Private Sub CommandButton1_Click()
   MsgBox "UserForm Click"
End Sub

我发现有两个问题。首先,在类中将
属性Let
更改为
属性集
。其次,在形式代码中,您需要说
Set o.First
。可能还有其他问题。此外,
evFirst
对象与
m_First
对象相同。
WithEvents
关键字只允许您为声明的对象编写自定义代码。本质上,您不需要先使用
m_
变量……这不是一种编码风格。这是为了满足人们的期望。另外,如果您的类有一个默认成员,那么let强制将真正改变成员的工作方式,使用相同的代码-这在客观上是错误的,根本不是样式问题。一个是正确的,另一个是乞求将来的bug发生。@Berryl-
ObjPtr
在被包装在
变体中后不可靠。在这种情况下,您需要使用
VarPtr
Debug.Assert VarPtr(o.First)=VarPtr(f.CommandButton1)
应该通过。这取决于您测试的内容。如果因为逻辑所在而测试表单,则会出现设计问题(Smart UI[anti]-模式),需要重构以获得更类似MVP的解决方案。我不为视图级逻辑编写单元测试,所以我的一行回答是“你不需要”。你将如何在C#中做完全相同的事情?你不会,因为你不会让表单在C#中运行该节目-所以,在VBA中也这样做!(我的博客上有几篇关于这方面的文章)