替代SendKeys" {Esc}"对于未绑定的文本框撤消

时间:2015-03-02 17:30:23

标签: ms-access sendkeys

我有未绑定文本框控件。用户输入一些有效文本并离开控件。然后用户返回控件并输入一些无效文本。我想向用户显示一条消息,然后将控件的值回滚到之前的状态将焦点保持在该控件

我尝试了以下方法,但没有一种能让我得到我想要的东西:


选项A :SendKeys

Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
    Cancel = DataIsInvalid(Me.MyTextBox.Value)
    If Cancel Then SendKeys "{Esc}"
End Sub    

这正是我想要的,但我真的想避免使用SendKeys。使用SendKeys会遇到许多问题:Vista+ compatibility,密钥被发送到其他应用程序等。


选项B :撤消控制方法

Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
    Cancel = DataIsInvalid(Me.MyTextBox.Value)
    If Cancel Then Me.MyTextBox.Undo
End Sub    

对于未绑定的控件(至少从MS Access 2002 / XP开始),这是简单的。此方法不会将MyTextBox的值还原为有效输入。但是,它确实允许用户将焦点更改为新控件,同时在Me.MyTextBox中保留无效输入!难以置信!!!


选项C :撤消表单

的方法
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
    Cancel = DataIsInvalid(Me.MyTextBox.Value)
    If Cancel Then Me.Form.Undo
End Sub    

Undo这里绝对没有。但至少它不会破坏BeforeUpdate Cancel = True代码并允许无效数据站立。


选项D :在BeforeUpdate事件中明确恢复旧值

Private mPrevMyTextBoxValue As Variant

Private Sub MyTextBox_AfterUpdate()
    mPrevMyTextBoxValue = Me.MyTextBox.Value
End Sub
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
    Cancel = DataIsInvalid(Me.MyTextBox.Value)
    If Cancel Then Me.MyTextBox.Value = mPrevMyTextBoxValue
    'If Cancel Then Me.MyTextBox.Text = mPrevMyTextBoxValue
End Sub    

尝试将以前的值分配给文本框的.Value.Text属性会导致出现相同的错误消息:

  

为此字段设置为BeforeUpdate或ValidationRule属性的宏或函数阻止{Program Name}在字段中保存数据。


选项E :在AfterUpdate事件中明确恢复旧值

Private mPrevMyTextBoxValue As Variant

Private Sub MyTextBox_AfterUpdate()
    If DataIsInvalid(Me.MyTextBox.Value) Then
        Me.MyTextBox.Value = mPrevMyTextBoxValue
        Me.MyTextBox.SetFocus
    Else
        mPrevMyTextBoxValue = Me.MyTextBox.Value
    End If
End Sub

这非常接近期望的行为。遗憾的是,由于AfterEpdate事件在处理Tab / Enter按键或鼠标单击事件之前运行,因此无法将注意力集中在控件上。因此,即使我们试图强调焦点到适当的控制(通过上面的.SetFocus语句),程序也会立即将焦点转移到用户选择的控件上。


在我看来,"对"这样做的方法是使用控件的.Undo方法。但是,这对于未绑定的控件不起作用。这是一个令人无法解释的缺点,特别是考虑到Escape按键为未绑定的字段执行此功能这一事实。

有更好的方法可以做到这一点,还是应该坚持使用SendKeys

2 个答案:

答案 0 :(得分:1)

在google上进入第3页后,我决定只是瞎逛,看看在尝试选项E时会发生什么样的排序。以下是我能够使用的最佳解决方法,让我们专注于“留在”文本框中有问题。

Private mPrevMyTextBoxValue As Variant

Private Sub Text0_AfterUpdate()
    If Me.Text0.Value = 0 Then
        Me.Text0.Value = mPrevMyTextBoxValue
        Me.Text12.SetFocus
        Me.Text0.SetFocus
    Else
        mPrevMyTextBoxValue = Me.Text0.Value
    End If
End Sub

0模拟验证失败。看起来如果你将焦点设置为别的东西,然后再将它设置回你正在使用的文本框,那么它将保留在那里。不幸的是,我没有答案。

编辑:我已经决定尝试编写我的理论,以确定其工作原理

Private blnGoToNextControl as Boolean

Private Function SetFocus(ctrl As control)

   blnGoToNextControl = True
   If ctrl.HasFocus = True Then 
    'Do nothing
   Else 
      ctrl.HasFocus = True 
      blnGoToNextControl = False
   End If
End Function 

这是我对SetFocus函数如何工作的想法。因此,在AfterUpdate事件运行之后,它将检查是否要转到下一个控件的标志,并查看它是否设置为false而不是转到下一个控件。

粗略的编码显然但希望这可以解释我的理论?

答案 1 :(得分:0)

如果未绑定,为什么不使用AfterUpdate事件:

Private Sub MyTextBox_AfterUpdate()
    If DataIsInvalid(Me!MyTextBox.Value) Then
        Me!MyTextBox.Value = Null
        Me!MyTextBox.SetFocus
    End If
End Sub   

或修改您的其他解决方案:

Private Sub MyTextBox_AfterUpdate()

    Static mPrevMyTextBoxValue As Variant

    If IsEmpty(mPrevMyTextBoxValue) Then
        mPrevMyTextBoxValue = Null
    End If

    If DataIsInvalid(Me!MyTextBox.Value) Then
        Me!MyTextBox.Value = mPrevMyTextBoxValue 
        Me!MyTextBox.SetFocus
    Else
        mPrevMyTextBoxValue = Me!MyTextBox.Value
    End If
End Sub

尝试将焦点从文本框移开,然后返回:

        Me!MyTextBox.Value = mPrevMyTextBoxValue 
        Me!SomeOtherControl.SetFocus
        Me!MyTextBox.SetFocus

另一个控件可能是一个几乎隐藏的小文本框。