Put code inside a loop to exit the loop after any mouse click
On a Userform, I'm blinking a frame Off/On by toggling its visiblity. It blinks a variable number of times and then stops, but in between blinks it checks for user activity. If there has been a mouse click anywhere on the form or on any of the contained controls then the blinking stops immediately.
This is what my blinker looks like.
For i = 1 To numberOfBlinks
<blink twice>
DoEvents
If <click detected> Then Exit Sub
Next i
Everything works fine except for the <click detected>
part. How do I do that from inside the 开发者_如何学Goloop?
Did you tried to change a global boolean variable on the mouseclick event to true (default false)?
Then try to check if this global boolean variable is true in <click detected>
.
This seems to work ok, but it looks like a lot of code just to detect a mouse click. For instance, I thought it should be possible to create a Class that contains all the Form Controls, so I could detect a click on any of them in one go, without having to check on each kind of control separately. I couldn't make that work and I'm hoping somebody can improve on this.
Just to restate what this does: On a Userform, a large frame named mapFrame holds any number of other frames and labels, and all those contained frames can hold any number of other frames and labels, but that's as deep as the nesting goes. I want to start a loop, (in this case the loop blinks a control off and on, but it could be any other loop) and wait for the user to click on any of the contained Frames or Labels to signal an exit from the loop. I also want to get the name of the control that was clicked.
I took the suggestion by therealmarv and used the click to set a public Boolean which gets tested inside the loop.
In a new Class Module:
Option Explicit
Public WithEvents classLabels As msForms.Label
Private Sub classLabels_Click()
clickedControlName = "" '<== Public String
With classLabels
If .Parent.Name = "mapFrame" Or _
.Parent.Parent.Name = "mapFrame" Then
isClickDetected = True '<== Public Boolean
clickedControlName = .Name
End If
End With
End Sub
In another new Class Module:
Option Explicit
Public WithEvents classFrames As msForms.Frame
Private Sub classFrames_Click()
clickedControlName = "" '<== Public String
With classFrames
If .Name = "mapFrame" Or _
.Parent.Name = "mapFrame" Or _
.Parent.Parent.Name = "mapFrame" Then
isClickDetected = True '<== Public Boolean
clickedControlName = .Name
End If
End With
End Sub
In a Form Module:
Option Explicit
Dim frames() As New clsFrames
Dim labels() As New clsLabels
Private Sub createFrameListeners()
Dim ctl As msForms.Control
Dim frameCount as Long
For Each ctl In Me.Controls
' Debug.Print TypeName(ctl): Stop
If TypeName(ctl) = "Frame" Then
frameCount = frameCount + 1
ReDim Preserve frames(1 To frameCount)
'Create the Frame Listener objects
Set frames(frameCount).classFrames = ctl
End If
Next ctl
End Sub
Private Sub createLabelListeners()
Dim ctl As msForms.Control
Dim LabelCount as Long
For Each ctl In Me.Controls
' Debug.Print TypeName(ctl): Stop
If TypeName(ctl) = "Label" Then
LabelCount = LabelCount + 1
ReDim Preserve labels(1 To LabelCount)
'Create the Label Listener objects
Set labels(LabelCount).classLabels = ctl
End If
Next ctl
End Sub
Function blinkThisControl(ctrl As Control, ByVal blinkCount As Long)
isClickDetected = False
Dim i As Integer
For i = 1 To blinkCount
' <blink ctrl twice>
DoEvents
If isClickDetected Then Exit Function
'name of clicked control will be in clickedControlName
Next i
End Function
Private Sub userform_initialize()
Call createFrameListeners
Call createLabelListeners
' do other stuff
End Sub
精彩评论