举个简单的例子 - 我有一个表单,在运行时动态创建一个图片,该图片具有清除其内容的“单击”事件。为此,我编写了一个自定义类来表示该图像对象。
在一个名为“imgForm”的空白用户表单中。
Dim oneImg As New clsImg 'our custom class
Private Sub UserForm_Initialize()
Set oneImg.myPic = Me.Controls.Add("Forms.Image.1") 'set some property of the class
oneImg.Init 'run some setup macro of the class
End Sub
在名为“clsImg”的类模块中
Public WithEvents myPic As MSForms.Image
Public Sub Init() 'can't put in Class_Initialise as it is called before the set statement - so myPic is still empty at that point
myPic.Picture = LoadPicture(path/image)
End Sub
Public Sub myPic_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
onePic.Picture = Nothing
End Sub
问题是,这不会显示更改,并且我意识到需要在某个地方加上
imgForm.Repaint
。问题是,在哪里加呢?尝试一:将其放在
clsImg
的Init()
子程序中(即在单击事件的末尾加上一行)。 这可以工作,但并不理想,因为该类只能与正确名称的用户窗体一起使用。第二个想法是将用户窗体作为参数传递给
Init()
。Public Sub Init(uf As UserForm) 'can't put in Class_Initialise as it is called before the set statement - so myPic is still empty at that point
myPic.Picture = LoadPicture(path/image)
uf.Repaint
End Sub
并称为
oneImg.Init Me
那种方法也可以,但这意味着无论在哪里需要重绘,我都必须传递参数,这也不理想——实际上,代码比这里展示的要复杂得多,所以我不想添加这个额外参数,除非必要。
第三个选项是我目前正在使用的,即将用户窗体对象传递到类中并在其中保存。
因此,通过在类模块的顶部使用
Public myForm As UserForm
,我可以使用 Init(uf As UserForm)
传递用户窗体并进行保存。Set myForm = uf 'Works with a private "myForm"/ class Property
或者我可以直接在用户表单代码中设置它。
Set clsImg.myForm = Me 'only if "myForm" is Public
但这对于内存有何作用 - 将用户表单保存为我的类中的变量会占用大量内存吗?请记住,在我的实际代码中,我声明了一个可以超过100个实例的clsImg
数组,因此如果该方法是在每个类中制作副本,我并不想这样做。另外,这很丑。
我真正想要的是...
...一种告诉用户表单需要重新绘制的方法,而不是直接从类中重新绘制。对我来说,这意味着我的类需要发生某些事件,而用户表单则通过一些自定义事件处理程序听到。就像Worksheet_Change一样,工作表对象引发一个更改事件,工作表类代码处理它。
是否可能实现这样的方法(我想我必须声明clsImg WithEvents
- 你可以为数组这样做吗?),或者是否有更好的选择。我正在寻找一种不会影响性能的方法,可以声明大量类,并且易于移植和阅读。这是我第一次使用类,所以我可能会错过一些非常明显的东西!
.parent
属性获取表单,请参见下面的答案。 - Nathan_Sav