当前位置: 首页 > 知识库问答 >
问题:

为什么MessageBox对SuppressKeyPress有影响?

郤坚诚
2023-03-14

下面是vb中的一个特殊情况。我搞乱了SuppressKeyPress属性,发现了一些奇怪的东西。

形势

假设我有一个名为txtName的输入框,我希望名称不带任何数字,当插入数字时,会弹出一个MessageBox并报告错误。

Private Sub TextBox1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles txtName.KeyDown
    If e.KeyCode >= Keys.D0 And e.KeyCode <= Keys.D9 And _
e.Modifiers <> Keys.Shift Then
        e.SuppressKeyPress = True
        MsgBox("Error - A Number has been pressed")
        'The number appeared in the text box.
    End If
End Sub

在这种情况下,由于某种奇怪的原因,如果我键入一个数字,它将被写入文本框中,尽管我抑制了按键。

我发现,如果我删除MsgBox行,数字将不会出现在输入框中。

Private Sub TextBox1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles txtName.KeyDown
    If e.KeyCode >= Keys.D0 And e.KeyCode <= Keys.D9 And _
e.Modifiers <> Keys.Shift Then
        e.SuppressKeyPress = True
        'The number did not appear in the text box.
    End If
End Sub

问题

这是怎么回事?为什么MsgBox“允许”按键被按下?为什么它对SubpressKeyPress属性有任何影响?

共有3个答案

吕博耘
2023-03-14

所以我测试了你的代码,我可以重现这种行为。我认为之所以会发生这种情况,是因为MsgBox(一个模式对话框)将调用应用程序。DoEvents导致消息被处理。

通过替换

MsgBox("Error - A Number has been pressed")

Application.DoEvents

你会得到同样的结果。

你应该在下面的帖子中阅读汉斯·帕桑的答案。他很好地解释了ShowDialog(参考MsgBox)和DoEvents之间的关系。

  • 应用程序的使用。DoEvents()
庞修贤
2023-03-14

我为那些不想干扰调用方法、手动启动新线程等的人找到了一个小技巧。

我的(旧)代码不起作用了

Private Sub textEditKeyPress(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.KeyValue = 220 Then
        e.SuppressKeyPress = True
        MessageBox.Show("\ not allowed. Use / instead.")
    End If
End Sub

通过将代码更改为

Private Async Sub tEditDropBoxFolderName_EditValueChanged(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.KeyValue = 220 Then
        e.SuppressKeyPress = True
        Await Task.Delay(100)
        MessageBox.Show("\ not allowed. Use / instead.")
    End If
End Sub

一切正常,我没有发现使用这个有任何副作用。

(代码由c#翻译,可能需要对vb进行一些修改。)

王昊
2023-03-14

这是使用MessageBox的一个非常典型的副作用,它可能会导致许多棘手的诊断问题。通过在消息队列中搜索任何按键事件并将其删除来实现SubpressKeyPress属性。但这只能在事件处理程序完成后发生。

问题是,它不会很快完成。您的MsgBox()调用正在接管,它开始自行泵送消息循环。就像对话框一样,相当于调用臭名昭著的DoEvents()方法。它会很容易地调度消息队列中的挂起消息,包括那些应该被抑制的按键消息。

解决此类问题的一个创可贴是在事件处理完成并且Winforms有机会清除按键消息后,稍后显示消息框。通过使用控件优雅地完成。BeginInvoke()方法:

Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyDown
    If e.KeyCode >= Keys.D0 And e.KeyCode <= Keys.D9 And e.Modifiers <> Keys.Shift Then
        e.SuppressKeyPress = True
        Me.BeginInvoke(New Action(Sub() MsgBox("Error - A Number has been pressed")))
    End If
End Sub

但真正的解决方法是使用正确的事件。您应该始终使用KeyPress事件来进行这种过滤。这也避免了在您使用KeyDown时始终存在的对用户活动键盘布局的非常痛苦的依赖。修复:

Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox1.KeyPress
    If e.KeyChar >= "0"c AndAlso e.KeyChar <= "9"c Then
        e.Handled = True
        MsgBox("I don't like digits")
    End If
End Sub

但话说回来,不要因为用户犯了一个简单的错误而使用消息框来打他耳光。

 类似资料:
  • 我在Apache HttpClients教程中读到关闭并丢弃连接。我的问题是,当我们使用一个只管理单个连接的时,我调用我是否无法重用同一个HttpClient,因为连接已经关闭并被丢弃?

  • 问题内容: 我有一个用Golang编写的小守护程序,该守护程序可以循环运行并完成一些工作。我发现,在使用CGO_ENABLE = 1或CGO_ENABLED = 0进行编译时,守护程序的行为会有所不同。例如,在CGO_ENABLE = 1(默认设置)的情况下,程序的VSZ在短时间内(在一小时内)膨胀到1-2GB。如果CGO_ENABLED = 0,则VSZ在很长一段时间(几天内)都相同。查看以下数

  • 问题内容: 我正在使用SQL Server2008。DateTime列“ DateFrom”上有一个非唯一的非聚集索引。我正在根据此列搜索表。我只是想知道 CONVERT()函数 对INDEX的影响,请参见以下内容: 我已经检查并发现没有区别。但是我在想,既然该列是CONVERTED的,那么SQL Server可能不会使用该索引,这是正确的吗? 如果这不是一个适当的问题,请原谅我。 问题答案: 通

  • 根据定义: noNamespaceSchema位置属性引用没有目标命名空间的XML Schema文档。 这个属性将如何改变解析的结果? 例如,以这个XML为例: 参考此模式: 我从架构中删除了以下命名空间声明: 即使在引用XML中不使用noNamespaceSchemaLocation属性,也不会引发错误。为什么我们一开始就需要这个属性?

  • 我正在做一个装在盒子里的计数器。我试图使这个计数器对不同的屏幕大小做出响应,但由于某些原因,我试图使用的媒体查询将无法工作。 我曾尝试将设备宽度更改为768px以下,但查询对计数器没有影响,我不确定原因。我已经包括了计数器的HTML/PHP代码以及CSS。有人知道为什么它不起作用吗 我已确保此标签包含在文档的标题中。 超文本标记语言: CSS:

  • 问题内容: 嵌入式注释如何影响数据库? SQL查询将如何改变? 使用注释的典型用例是什么? 问题答案: 嵌入式注释如何影响数据库? 它根本不影响它。在ORM提供程序层上,来自嵌入式实体的所有字段都 将 与父实体 合并 ,并像对待它们始终在其中声明一样。换句话说,它的工作方式就好像您将所有字段,获取器和设置器直接复制到包含嵌入式对象的实体中一样。 SQL查询将如何改变? 他们不会。您无需更改任何内容