如何清除键盘缓冲区中的过时消息
我的 WinForms 应用程序有一个按钮。该按钮有加速键(例如Alt+L)。按下按钮时,我处理 Click 事件并禁用 UI 以防止进一步单击按钮,直到处理完成。但是,当使用键盘按下加速键时,这些击键会排队并在 UI 再次启用时立即得到处理。我不想要这个。我的问题是如何清除/刷新键盘缓冲区?
如果我使用 KeyPress 或 KeyDown 来吃掉这些字符,我不知道它们何时被收到。我只想抑制在我仍在处理第一个 Click 事件时到达的旧/过时消息。
My WinForms application has a button. This button has accelerator key (e.g. Alt+L). When button is pressed I handle the Click event and disable UI to prevent further button clicks until processing is finished. However, when accelerator key is pressed using keyboard those keystrokes are queued and get processed as soon as UI is enabled again. I don't want this. My question is how to clear/flush keyboard buffer?
If I use KeyPress or KeyDown to eat those characters I don't know when they have been received. I only want to suppress old/stale messages that arrived when I was still processing first Click event.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,您对问题的理论确实与我和 madmik3 在上面的评论交流中提出的理论一致。您的应用程序在 UI 线程上执行的工作量实际上阻止了它处理其他事件,包括用户的击键。每当您的应用程序完成其耗时的前台任务时,这些就会排队等待稍后执行。这些都是现代抢占式多任务操作系统的危险。当然,在不发布您的实际代码的情况下,我或其他任何人能做的最好的事情就是根据我们的经验推测问题是什么。
快速检查确认情况确实如此,方法是抛出
Application.DoEvents
进入您的处理循环。这将允许操作系统立即处理击键,这将全部失败,因为按钮已被禁用。 (对于Enabled
属性设置为“False”的Button
控件,无论是由鼠标还是键盘快捷键启动的Click
事件都不会引发“。)这是最接近“刷新缓冲区”之类的内容。我怀疑您无论如何都会收到KeyDown
或KeyPress
事件,直到任何长时间运行的任务完成之后。如果这解决了问题,长期解决方案是生成一个新线程并执行您需要在其中执行的任何处理,而不是在 UI 线程上执行。这将防止您阻塞 UI 线程,并且假设正确禁用了 Button 控件,则会导致击键被丢弃,因为它们“单击”的按钮处于不可单击状态。创建新线程的最简单方法是使用
BackgroundWorker
组件。该文档包含一个非常好的示例。Yes, indeed your theory of the problem is consistent with that proposed by both myself and madmik3 in the comment exchange above. The amount of work your application is doing on the UI thread is effectively blocking it from processing other events, including keystrokes by the user. Those are getting queued for later execution whenever your application finishes its time-consuming foreground task. Those are the perils of a modern-day, pre-emptive multitasking OS. Of course, without posting your actual code, the best I or anyone else can do is speculate about what the problem is, given our experience.
The quick check to confirm that this is actually the case is to toss
Application.DoEvents
into your processing loop. That will allow the OS to handle the keystrokes immediately, which will all fail because the button has been disabled. (Click
events, whether initiated by the mouse or keyboard shortcuts, are not raised for aButton
control that has itsEnabled
property set to "False".) This is the closest you'll get to anything like "flushing the buffers". I doubt you're receivingKeyDown
orKeyPress
events anyway until after whatever long-running task has completed.If that fixes the problem, the long-term solution is to spawn a new thread and perform whatever processing you need to do there, instead of on your UI thread. This will prevent you from blocking your UI thread, and, assuming the
Button
control is correctly disabled, cause the keystrokes to get thrown away because the button they "click" is in a non-clickable state. The simplest way to create a new thread is using theBackgroundWorker
component. The documentation contains a pretty good example.