如何检测用户窗体控件是否因鼠标点击与标签失去焦点/正在退出

时间:2018-02-09 18:01:07

标签: excel-vba vba excel

背景

我有一个带有倍数的用户窗体,一个文本框和一个命令按钮。每个多页还有许多文本框。我希望能够通过从第一页上的最后一个文本框到第二页上的第一个文本框(例如......)以及从最后一页上的最后一个文本框到文本框的标签(向前和向后)移动低于倍数。

我以为我已经为此创建了一个解决方案(如下所示);但是,我的解决方案不允许用户(鼠标)单击非下一个选项卡或多页对象下面的文本框来中断选项卡顺序。相反,他们必须通过多页对象标记整个方式,这可能涉及相当多的不必要的标签。

尝试

我最初尝试在每次tabDirect运行结束时将全局变量NonTab重置为Multipage_Exit。结果是第一次点击(到不同的页面或在多页对象之外)被视为选项卡,而第二次实际上被视为鼠标点击。

我还尝试在userform中的每个鼠标点击事件中将tabDirect更改为NonTab。但是,当前页面外的控件的鼠标单击事件从未发生过。

经过研究,看起来好像什么时候在事件所在的多页下面的文本框上发生鼠标点击:

  1. 留下多页
  2. 输入文本框
  3. TextBox_MouseDown
  4. MouseDown事件后是否还有其他事件?或者在退出事件期间判断是否单击鼠标或按下了哪些键的另一种方法是什么?

    备注

    我知道另一个建议是通过插入一个命令按钮来完成页面的标签,当选项卡时,它会“翻页”,可以说是多页对象中的下一页。我希望有一条看起来更干净的路线;因此multipage_exit sub。

    中的代码

    我也完全清楚,我的问题的答案最终可能“不可能”。然而,人们有时会为困难问题提出惊人的解决方案,我想我希望这将成为其中一个时代。

    尽管如此,我也对其他建议/建议持开放态度,以便在多页对象的页面中进行标记。

    初始代码

    全局变量

    Public tabDirect As tabbing
    
    Public Enum tabbing
        [_First] = 1
        NonTab = 1
        Forwards
        Backwards
        [_Last] = 3
    End Enum
    

    Userform Sub

    Private Sub Multipage_Exit(ByVal Cancel As MSForms.ReturnBoolean)
        Dim counter As Integer
        Dim cnt As Integer
    
        If tabDirect <> NonTab Then 'If not tabbing, skip to end of sub
            ' determines value of next page
            If tabDirect = Backwards Then
                counter = Multipage.Value - 1
            ElseIf tabDirect = Forwards Then
                counter = Multipage.Value + 1
            End If
    
            'If tabbing backwards while on the first page,
            'the counter would have a value of -1 here
            If counter < 0 Then '
                counter = Multipage.Pages.Count - 1
            End If
    
            'Only way for counter to equal Multipage.Pages.Count,
            'is if tabbing forward off of last page.
            'Desired result is to leave the multipage
            If counter <> Multipage.Pages.Count Then
                'Tabbing forwards: want first textbox, tabbing backwards: want last
                If tabDirect = Backwards Then
                    cnt = Multipage.Pages(counter).Controls.Count - 2 ' skip over label
                Else
                    cnt = 0
                End If
    
                Multipage.Value = counter
    
                With Multipage.Pages(counter).Controls(cnt)
                    .SetFocus
                    .SelStart = 0
                    .SelLength = Len(.Value)
                End With
    
                'Fixing scollbar
                If tabDirect = Backwards Then
                    Multipage.Pages(counter).ScrollTop = Multipage.Pages(counter).ScrollHeight
                Else
                    Multipage.Pages(counter).ScrollTop = 0
                End If
    
                'Don't want to cancel when leaving first page backwards
                If tabDirect <> Backwards Or counter <> Multipage.Pages.Count - 1 Then
                    Cancel = True
                End If
            Else
                Multipage.Value = 0
                Multipage.Pages(0).ScrollTop = 0
            End If
        End If
    End Sub
    

    表格中每个文本框的文本框类中的代码

    Private Sub Textbox_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    
        'KeyCode 9 = tab
        If KeyCode = 9 And Shift = 1 Then
            tabDirect = Backwards
        ElseIf KeyCode = 9 Then
            tabDirect = Forwards
        Else
            tabDirect = NonTab
        End If
    End Sub
    

    userform

    上每个控件的MouseDown事件中的代码
    Private Sub Control_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
        tabDirect = NonTab
    End Sub
    

1 个答案:

答案 0 :(得分:0)

虽然我无法找到区分标签和鼠标点击的方法,但我确实找到了另一种方法来确定是否退出多边形而不是标签到下一个文本框。

我假设如果多重退出事件由Tab键触发,则最近输入的文本框将是页面上的第一个(向后跳转)或最后一个(向前跳转)文本框。因此,如果当前文本框的名称与我正在观看的名称(第一个或最后一个,视情况而定)相匹配,那么多页应继续到下一页(根据我之前的逻辑)。因此,我做了如下所示的更改。

更改代码

添加了全局变量

Public enteredBox As String

添加到每个KeyDown和MouseDown事件的代码

enteredBox = Control.Name

编辑退出活动,新代码如下所示

-----------
|  New Code
-----------

Private Sub Multipage_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Dim counter As Integer
    Dim cnt As Integer
-----------------------------------
|   Dim idWanted As Long
|   Dim temp As Integer
|   Dim endCount As Integer
-----------------------------------

    If tabDirect <> NonTab Then 'If not tabbing, skip to end of sub
        If tabDirect = Backwards Then
            counter = Multipage.Value - 1

            If counter < 0 Then
                counter = Multipage.Pages.Count - 1
            End If

            cnt = Multipage.Pages(counter).Controls.Count - 2
-------------------------------------------------------------
|           idWanted = 2
|           endCount = Multipage.Value - 1
-------------------------------------------------------------
        ElseIf tabDirect = Forwards Then
            counter = Multipage.Value + 1
            cnt = 0
-------------------------------------------------------------
|           idWanted = 1
|           endCount = Multipage.Value
-------------------------------------------------------------
        End If

---------------------------------------------------------------------------
|       For temp = 0 To endCount
|           idWanted = idWanted + Multipage.Pages(temp).Controls.Count / 2
|           'Division by two since each page has an associated label for each textbox
|       Next temp
|
|       'textArr is an array of textboxes on the form
|       'where textboxes were added in the order they appear on each page
|       If textArr(idWanted).Name = enteredBox Then
---------------------------------------------------------------------------

            'Only way for counter to equal Multipage.Pages.Count,
            'is if tabbing forward off of last page.
            'Desired result is to leave the multipage
            If counter <> Multipage.Pages.Count Then
                'Tabbing forwards: want first textbox, tabbing backwards: want last
                If tabDirect = Backwards Then
                    cnt = Multipage.Pages(counter).Controls.Count - 2 ' skip over label
                Else
                    cnt = 0
                End If

                Multipage.Value = counter

                With Multipage.Pages(counter).Controls(cnt)
                    .SetFocus
                    .SelStart = 0
                    .SelLength = Len(.Value)
                End With

                'Fixing scollbar
                If tabDirect = Backwards Then
                    Multipage.Pages(counter).ScrollTop = Multipage.Pages(counter).ScrollHeight
                Else
                    Multipage.Pages(counter).ScrollTop = 0
                End If

                'Don't want to cancel when leaving first page backwards
                If tabDirect <> Backwards Or counter <> Multipage.Pages.Count - 1 Then
                    Cancel = True
                End If
            Else
                Multipage.Value = 0
                Multipage.Pages(0).ScrollTop = 0
            End If
--------------------
|       End If
--------------------
    End If
End Sub