除非我破坏userform初始化

时间:2017-08-13 16:49:51

标签: vba excel-vba events userform excel

这是以下问题的后续行动: Can't set Userform.KeyPreview to true

回顾一下:目标是使用一些命令按钮和一个包含复选框的框架构建一个表单。复选框在框架中的userform_initialize处动态填充,以便用户可以滚动它们。我的问题是键盘快捷键。不可能为每个复选框强制写入KeyDown处理程序,因为我不知道哪些复选框存在。不幸的是,Excel不支持KeyPreview所以我不得不模拟我自己的版本。感谢@UGP为我提供了有前途的途径,但似乎不行......

首先,这是我的名为clsReasonPickKP的类模块。我为每个复选框创建了一个新实例来监听KeyDown个事件:

Option Explicit

Dim WithEvents vChkBx As MSForms.CheckBox

Friend Sub initializeListener(cControl As control)
Set vChkBx = cControl
End Sub

Private Sub vChkBx_KeyDown(ByVal keyCode As MSForms.ReturnInteger, ByVal shift As Integer)
frm2.keyChooser keyCode
End Sub

frm2.keyChooser keyCode启动位于userform代码模块中的快速子。代码如下:

Public Sub keyChooser(ByVal keyCode As MSForms.ReturnInteger)
Select Case keyCode
    Case vbKeyEscape: cancelBtn_Click
    Case vbKeyReturn: completeDecision_Click
    Case vbKeyN: customizeNote_Click
    Case vbKeyS: resetDecisionNote_Click
    Case vbKeyR: chkRefGrnds_Click
End Select
End Sub

我已经复制了下面UserForm_Initialize子的相关部分。循环为每个创建复选框和事件监听器。

Sub UserForm_Initialize()
Dim x As Long, maxWidth as Long
Dim cControl As control
Dim keyPreviewCollection As New Collection
Dim keyPreviewer As clsReasonPickKP
For x = 1 To dTbl.Rows.Count - 1
    Set cControl = chkBoxFrame.Controls.Add("Forms.CheckBox.1", "chkBox" & x, True)
    With cControl
        .AutoSize = True
        .WordWrap = False
        .Left = 10
        .Top = 16 * x - 12
        .Caption = dTbl(x, 1).Value
        If .Width > maxWidth Then maxWidth = .Width
    End With
Set keyPreviewer = New clsReasonPickKP
keyPreviewer.initializeListener cControl
keyPreviewCollection.Add keyPreviewer
Next x
'Additional initialization code here
End Sub

奇怪的是,除非我在keyPreviewCollection.Add keyPreviewer之后的某个时间中断代码,否则侦听器似乎不会处理该事件。例如,如果我在Next xx > 1设置断点,然后完成初始化,那么当表单完成初始化并显示监听器调用keyChooser并且一切正常时;如果我不破坏这样的代码,它不会捕获事件或调用sub等。

为了解决问题,我尝试不将keyPreviewer添加到集合中,然后听众也无法工作,无论我是否或何时休息。它似乎将对象添加到集合中,并在将其添加到集合后处于代码中断模式,以某种方式使侦听器捕获事件。

同样有趣的是,如果我在vChkBx_KeyDown模块中放置断点,它会在引发事件时中断(假设如上所述适当中断)。然而,在我运行代码之后,当它被引发时,它会停止处理KeyDown事件。

如果有帮助,我目前正在使用Excel 2010。

有人知道发生了什么吗?知道如何解决这个问题,即使采用不同的代码方法吗?

永远感谢大家的帮助。

2 个答案:

答案 0 :(得分:1)

事实证明,这个问题非常简单,就在眼前。我只需要在我的用户表单代码模块中公开keyPreviewerkeyPreviewCollection个变量。

仍然没有回答为什么在将对象添加到集合后破坏代码执行的原因使得VBA将其视为公共,但是很高兴它一切正常。

答案 1 :(得分:0)

DoEvents可能是故障单。请参阅下面的文章:

https://www.automateexcel.com/vba/doevents/