如何使用 Class 模块修改用户窗体标签的外观?
How to modify the appearance of UserForm Labels using Class Module?
我有这个用户窗体(图 1),我正在尝试通过 Class 模块应用一些自定义。因此,我的第一个目标是在单击时修改标签格式(图 2)。到目前为止一切顺利,我已经通过 Class 模块“cLabels”完成了这项工作。现在,我的第二个目标是(这是我坚持的目标)将一些其他颜色应用于上述标签。关键是,我不知道如何完成这个。
我试图创建另一个名为“cUserForm”的 class 模块,但我不知道如何将修改后的标签传递给 cUserForm Class 模块并使用其 MouseMove 事件。我知道我可以使用 MouseMove 事件通过标准用户窗体模块应用修改,但问题是,我不想在我的用户窗体模块中使用任何类似的代码,我希望 class 模块执行“脏”工作。大家有什么想法可以解决这个问题吗?
附加信息(但对解决问题不重要):我的最终目标是制作像这样的“按钮”https://drive.google.com/file/d/1ev_LNgxPqjMv0dtzlF7GSo7SOq0wDbR2/view?usp=sharing,具有一些效果,例如 MouseHover、TabPress 等。 VBA 按钮非常难看。仅作记录,我已经在标准用户窗体模块中完成了所有这些工作(如果有人想让工作簿看到我在说什么,我有),但最终结果只是一团糟,代码太多(并且它只是修改用户窗体外观的代码,想象一下当我放一些代码来执行某些操作时,我的天啊)。
Image 1
Image 2
这是我目前的情况:
用户窗体模块
Option Explicit
Private ObjLabel As cLabels
Private ObjUserForm As cUserForm
Private Sub UserForm_Initialize()
Set ObjLabel = New cLabels
ObjLabel.CallClasse Me
Set ObjUserForm = New cUserForm
Set ObjUserForm.UserFormValue = Me
End Sub
c标签
Option Explicit
'## Events/Variables/Collections
Private WithEvents clsLabel As MSForms.Label
Private ClasseObject As cLabels
Private LabelCollection As New Collection
'## Properties
Public Property Get ActiveLabel() As MSForms.Label
Set ActiveLabel = clsLabel
End Property
Public Property Set ActiveLabel(Value As MSForms.Label)
Set clsLabel = Value
End Property
'## Procedures/Methods
Private Sub clsLabel_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
LabelHovered
End Sub
Public Sub CallClasse(MainObject As MSForms.UserForm)
Dim ctrl As MSForms.Control
For Each ctrl In MainObject.Controls
If TypeOf ctrl Is MSForms.Label Then
Set ClasseObject = New cLabels
Set ClasseObject.ActiveLabel = ctrl
LabelCollection.Add ClasseObject
End If
Next ctrl
End Sub
Private Sub LabelHovered()
ActiveLabel.BackColor = vbYellow
End Sub
cUserForm
Option Explicit
'## Events/Variables/Collections
Private WithEvents clsUserForm As MSForms.UserForm
Private mActiveLabel As MSForms.Label
Private ObjLabel As New cLabels
'## Properties
Public Property Get UserFormValue() As MSForms.UserForm
Set UserFormValue = clsUserForm
End Property
Public Property Set UserFormValue(Value As MSForms.UserForm)
Set clsUserForm = Value
End Property
Public Property Get ActiveLabel() As MSForms.Label
Set ActiveLabel = mActiveLabel
End Property
Public Property Set ActiveLabel(Value As MSForms.Label)
Set mActiveLabel = Value
End Property
'## Procedures
Private Sub clsUserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'MsgBox ObjLabel.ActiveLabel.BackColor 'Got an error
End Sub
工作簿:
https://drive.google.com/file/d/1cLG4pLmC-jDaysjd_dK0EFuJ_LqYqJ-u/view?usp=sharing
您无需创建单独的 class 模块来更改表单中的内容。只需在表单后面的代码中添加事件处理方法。 (在表单编辑器中,右键单击表单并select“查看代码”。)
您可以使用按钮的 MouseMove
事件更改其颜色,然后使用表单的 MouseMove
事件重置按钮颜色,如下所示:
Private Sub UserForm_MouseMove(ByVal Button As Integer, _
ByVal Shift As Integer, _
ByVal X As Single, _
ByVal Y As Single)
CommandButton1.BackColor = &H8000000F
End Sub
Private Sub CommandButton1_MouseMove(ByVal Button As Integer, _
ByVal Shift As Integer, _
ByVal X As Single, _
ByVal Y As Single)
CommandButton1.BackColor = vbYellow
End Sub
我发现您的问题非常有趣,并且我对如何执行此操作有一些不同的、更面向对象的看法。我尝试实施 Observer Pattern 以获得所描述的效果。 (作为旁注,通常我会使用接口来概括一个解决方案,但对于这个快速演示,我将展示几个紧密耦合的 类 来完成工作)
请允许我先介绍一下我的所有组件:
类:
LabelObserver
Option Explicit
Private WithEvents mInteralObj As MSForms.label
Private mBackGroundColor As Long
Private mMouseOverColor As Long
Private Const clGREY As Long = &H8000000F
'// "Constructor"
Public Sub Init(label As MSForms.label, _
Optional mouseOverColor As Long = clGREY, _
Optional backGroundColor As Long = clGREY)
Set mInteralObj = label
mBackGroundColor = backGroundColor
mMouseOverColor = mouseOverColor
End Sub
Private Sub Class_Terminate()
Set mInteralObj = Nothing
End Sub
Public Sub MouseLeft()
'//Remove Highlight
mInteralObj.BackColor = mBackGroundColor
End Sub
Private Sub mInteralObj_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'//Highlight
mInteralObj.BackColor = mMouseOverColor
End Sub
LabelNotifier
Option Explicit
Private observersCollection As Collection
Private Sub Class_Initialize()
Set observersCollection = New Collection
End Sub
Public Sub AddObserver(observer As LabelObserver)
observersCollection.Add observer
End Sub
Public Sub RemoveObserver(observer As LabelObserver)
Dim i As Long
'// We have to search through the collection to find the observer to remove
For i = 1 To observersCollection.Count
If observersCollection(i) Is observer Then
observersCollection.Remove i
Exit Sub
End If
Next i
End Sub
Public Function ObserverCount() As Integer
ObserverCount = observersCollection.Count
End Function
Public Sub Notify()
Dim obs As LabelObserver
If Me.ObserverCount > 0 Then
For Each obs In observersCollection
'//call each observer's MouseLeft method
obs.MouseLeft
Next obs
End If
End Sub
Private Sub Class_Terminate()
Set observersCollection = Nothing
End Sub
模块:
LabelObserverFactory (这是可选的 - 它只是提供了一种创建有效 LabelObservers
的精简方式)
Option Explicit
Public Function NewYellowHighlightCustomLabel(label As MSForms.label) As LabelObserver
Dim product As New LabelObserver
product.Init label, vbYellow
Set NewYellowHighlightCustomLabel = product
End Function
Public Function NewRedHighlightCustomLabel(label As MSForms.label) As LabelObserver
Dim product As New LabelObserver
product.Init label, vbRed
Set NewRedHighlightCustomLabel = product
End Function
用户窗体
MyForm (请注意,为了演示目的,此表单具有三个带有默认名称的标签)
Option Explicit
Private notifier As LabelNotifier
Private Sub UserForm_Initialize()
Set notifier = New LabelNotifier
'//add controls to be notified
notifier.AddObserver LabelObserverFactory.NewYellowHighlightCustomLabel(Me.Label1)
notifier.AddObserver LabelObserverFactory.NewRedHighlightCustomLabel(Me.Label2)
notifier.AddObserver LabelObserverFactory.NewYellowHighlightCustomLabel(Me.Label3)
End Sub
Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'//Notify labels that mouse has left them
notifier.Notify
End Sub
Private Sub UserForm_Terminate()
Set notifier = Nothing
End Sub
现在,解释一下这里发生了什么:
表单有一个 LabelNotifier 对象,它在表单初始化时建立,它将用来通知我们的标签鼠标已经离开它们。我们通过侦听窗体的 MouseMove 事件来完成此操作。 (我知道你试图避免使用这个,但希望我们的代码只有一行代码,无论你影响多少标签,都能满足在别处封装逻辑的愿望。) 当我们移动鼠标时,我们会让通知程序做它唯一的工作,向我们添加的所有标签发送消息。
LabelObserver 是 LabelNotifier 的对应部分。标签观察员负责告诉标签更改颜色以及使用哪种颜色。
即使您不喜欢这个实现,我也乐在其中。 :-)
我有这个用户窗体(图 1),我正在尝试通过 Class 模块应用一些自定义。因此,我的第一个目标是在单击时修改标签格式(图 2)。到目前为止一切顺利,我已经通过 Class 模块“cLabels”完成了这项工作。现在,我的第二个目标是(这是我坚持的目标)将一些其他颜色应用于上述标签。关键是,我不知道如何完成这个。
我试图创建另一个名为“cUserForm”的 class 模块,但我不知道如何将修改后的标签传递给 cUserForm Class 模块并使用其 MouseMove 事件。我知道我可以使用 MouseMove 事件通过标准用户窗体模块应用修改,但问题是,我不想在我的用户窗体模块中使用任何类似的代码,我希望 class 模块执行“脏”工作。大家有什么想法可以解决这个问题吗?
附加信息(但对解决问题不重要):我的最终目标是制作像这样的“按钮”https://drive.google.com/file/d/1ev_LNgxPqjMv0dtzlF7GSo7SOq0wDbR2/view?usp=sharing,具有一些效果,例如 MouseHover、TabPress 等。 VBA 按钮非常难看。仅作记录,我已经在标准用户窗体模块中完成了所有这些工作(如果有人想让工作簿看到我在说什么,我有),但最终结果只是一团糟,代码太多(并且它只是修改用户窗体外观的代码,想象一下当我放一些代码来执行某些操作时,我的天啊)。
Image 1
Image 2
这是我目前的情况:
用户窗体模块
Option Explicit
Private ObjLabel As cLabels
Private ObjUserForm As cUserForm
Private Sub UserForm_Initialize()
Set ObjLabel = New cLabels
ObjLabel.CallClasse Me
Set ObjUserForm = New cUserForm
Set ObjUserForm.UserFormValue = Me
End Sub
c标签
Option Explicit
'## Events/Variables/Collections
Private WithEvents clsLabel As MSForms.Label
Private ClasseObject As cLabels
Private LabelCollection As New Collection
'## Properties
Public Property Get ActiveLabel() As MSForms.Label
Set ActiveLabel = clsLabel
End Property
Public Property Set ActiveLabel(Value As MSForms.Label)
Set clsLabel = Value
End Property
'## Procedures/Methods
Private Sub clsLabel_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
LabelHovered
End Sub
Public Sub CallClasse(MainObject As MSForms.UserForm)
Dim ctrl As MSForms.Control
For Each ctrl In MainObject.Controls
If TypeOf ctrl Is MSForms.Label Then
Set ClasseObject = New cLabels
Set ClasseObject.ActiveLabel = ctrl
LabelCollection.Add ClasseObject
End If
Next ctrl
End Sub
Private Sub LabelHovered()
ActiveLabel.BackColor = vbYellow
End Sub
cUserForm
Option Explicit
'## Events/Variables/Collections
Private WithEvents clsUserForm As MSForms.UserForm
Private mActiveLabel As MSForms.Label
Private ObjLabel As New cLabels
'## Properties
Public Property Get UserFormValue() As MSForms.UserForm
Set UserFormValue = clsUserForm
End Property
Public Property Set UserFormValue(Value As MSForms.UserForm)
Set clsUserForm = Value
End Property
Public Property Get ActiveLabel() As MSForms.Label
Set ActiveLabel = mActiveLabel
End Property
Public Property Set ActiveLabel(Value As MSForms.Label)
Set mActiveLabel = Value
End Property
'## Procedures
Private Sub clsUserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'MsgBox ObjLabel.ActiveLabel.BackColor 'Got an error
End Sub
工作簿: https://drive.google.com/file/d/1cLG4pLmC-jDaysjd_dK0EFuJ_LqYqJ-u/view?usp=sharing
您无需创建单独的 class 模块来更改表单中的内容。只需在表单后面的代码中添加事件处理方法。 (在表单编辑器中,右键单击表单并select“查看代码”。)
您可以使用按钮的 MouseMove
事件更改其颜色,然后使用表单的 MouseMove
事件重置按钮颜色,如下所示:
Private Sub UserForm_MouseMove(ByVal Button As Integer, _
ByVal Shift As Integer, _
ByVal X As Single, _
ByVal Y As Single)
CommandButton1.BackColor = &H8000000F
End Sub
Private Sub CommandButton1_MouseMove(ByVal Button As Integer, _
ByVal Shift As Integer, _
ByVal X As Single, _
ByVal Y As Single)
CommandButton1.BackColor = vbYellow
End Sub
我发现您的问题非常有趣,并且我对如何执行此操作有一些不同的、更面向对象的看法。我尝试实施 Observer Pattern 以获得所描述的效果。 (作为旁注,通常我会使用接口来概括一个解决方案,但对于这个快速演示,我将展示几个紧密耦合的 类 来完成工作)
请允许我先介绍一下我的所有组件:
类:
LabelObserver
Option Explicit
Private WithEvents mInteralObj As MSForms.label
Private mBackGroundColor As Long
Private mMouseOverColor As Long
Private Const clGREY As Long = &H8000000F
'// "Constructor"
Public Sub Init(label As MSForms.label, _
Optional mouseOverColor As Long = clGREY, _
Optional backGroundColor As Long = clGREY)
Set mInteralObj = label
mBackGroundColor = backGroundColor
mMouseOverColor = mouseOverColor
End Sub
Private Sub Class_Terminate()
Set mInteralObj = Nothing
End Sub
Public Sub MouseLeft()
'//Remove Highlight
mInteralObj.BackColor = mBackGroundColor
End Sub
Private Sub mInteralObj_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'//Highlight
mInteralObj.BackColor = mMouseOverColor
End Sub
LabelNotifier
Option Explicit
Private observersCollection As Collection
Private Sub Class_Initialize()
Set observersCollection = New Collection
End Sub
Public Sub AddObserver(observer As LabelObserver)
observersCollection.Add observer
End Sub
Public Sub RemoveObserver(observer As LabelObserver)
Dim i As Long
'// We have to search through the collection to find the observer to remove
For i = 1 To observersCollection.Count
If observersCollection(i) Is observer Then
observersCollection.Remove i
Exit Sub
End If
Next i
End Sub
Public Function ObserverCount() As Integer
ObserverCount = observersCollection.Count
End Function
Public Sub Notify()
Dim obs As LabelObserver
If Me.ObserverCount > 0 Then
For Each obs In observersCollection
'//call each observer's MouseLeft method
obs.MouseLeft
Next obs
End If
End Sub
Private Sub Class_Terminate()
Set observersCollection = Nothing
End Sub
模块:
LabelObserverFactory (这是可选的 - 它只是提供了一种创建有效 LabelObservers
的精简方式)
Option Explicit
Public Function NewYellowHighlightCustomLabel(label As MSForms.label) As LabelObserver
Dim product As New LabelObserver
product.Init label, vbYellow
Set NewYellowHighlightCustomLabel = product
End Function
Public Function NewRedHighlightCustomLabel(label As MSForms.label) As LabelObserver
Dim product As New LabelObserver
product.Init label, vbRed
Set NewRedHighlightCustomLabel = product
End Function
用户窗体
MyForm (请注意,为了演示目的,此表单具有三个带有默认名称的标签)
Option Explicit
Private notifier As LabelNotifier
Private Sub UserForm_Initialize()
Set notifier = New LabelNotifier
'//add controls to be notified
notifier.AddObserver LabelObserverFactory.NewYellowHighlightCustomLabel(Me.Label1)
notifier.AddObserver LabelObserverFactory.NewRedHighlightCustomLabel(Me.Label2)
notifier.AddObserver LabelObserverFactory.NewYellowHighlightCustomLabel(Me.Label3)
End Sub
Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'//Notify labels that mouse has left them
notifier.Notify
End Sub
Private Sub UserForm_Terminate()
Set notifier = Nothing
End Sub
现在,解释一下这里发生了什么:
表单有一个 LabelNotifier 对象,它在表单初始化时建立,它将用来通知我们的标签鼠标已经离开它们。我们通过侦听窗体的 MouseMove 事件来完成此操作。 (我知道你试图避免使用这个,但希望我们的代码只有一行代码,无论你影响多少标签,都能满足在别处封装逻辑的愿望。) 当我们移动鼠标时,我们会让通知程序做它唯一的工作,向我们添加的所有标签发送消息。
LabelObserver 是 LabelNotifier 的对应部分。标签观察员负责告诉标签更改颜色以及使用哪种颜色。
即使您不喜欢这个实现,我也乐在其中。 :-)