windows 如何阻止所有键盘和鼠标输入到我的 WinForms 应用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1328746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I block all keyboard and mouse input to my WinForms app?
提问by Jim Clark
I have a WinForms app that is retrieving data from a web service on a worker thread and I need to disable all input to my app until the data is loaded.
我有一个 WinForms 应用程序,它从工作线程上的 Web 服务中检索数据,我需要在加载数据之前禁用我的应用程序的所有输入。
Currently, I create a semi-transparent form and place it over my application. When the data call completes I close this overlay form. This works fine accept that it causes considerable performance problems for users running the application over terminal services. I tried making the overlay entirely transparent but that still triggers two redraws of the entire window so this did not help at all.
目前,我创建了一个半透明的表单并将其放在我的应用程序上。数据调用完成后,我关闭此覆盖表单。这可以正常工作,但它会导致通过终端服务运行应用程序的用户出现相当大的性能问题。我尝试使覆盖层完全透明,但这仍然会触发整个窗口的两次重绘,因此这根本没有帮助。
I know that a common recommendation for handling this is to disable all the controls, but that would also redraw much of the screen so I'm looking for another way to block all user input. Any assistance would be greatly appreciated!
我知道处理这个问题的一个常见建议是禁用所有控件,但这也会重绘大部分屏幕,所以我正在寻找另一种方法来阻止所有用户输入。任何帮助将不胜感激!
UPDATE: I should have mentioned that we have considered the modal dialog. Currently we show the overlay, start the data access thread then construct the form. If there is no better way to block input (App.BlockInput() might be nice) then we could use the modal dialog idea, but we would need to wait until the form construction had completed and there isn't currently a nice, central location to do this.
更新:我应该提到我们已经考虑了模态对话框。目前我们显示覆盖层,启动数据访问线程然后构造表单。如果没有更好的方法来阻止输入(App.BlockInput() 可能很好),那么我们可以使用模态对话框的想法,但我们需要等到表单构建完成并且目前没有一个很好的、中央的位置来做到这一点。
回答by Nikolay R
You could display a small modal (modalForm.ShowDialog(yourForm)
) form with progress bar rolling on top of your app. This won't cause big areas to be redrawed.
您可以显示一个小的模态 ( modalForm.ShowDialog(yourForm)
) 表单,进度条在您的应用程序顶部滚动。这不会导致重绘大区域。
回答by Daniel Pryden
If your app really is blocked while the operation is running, I'd do what Microsoft frequently does: open a modal dialog box with some kind of throbber animation or ProgressBar, and a Cancel button. Redraw is limited because you're only drawing the size of the new dialog, and input to the rest of your application is blocked because the dialog is modal. Also, users are much more willing to wait when you have some kind of status updates and or animation, because it looks like the computer is "working".
如果您的应用程序在操作运行时真的被阻止,我会做微软经常做的事情:打开一个带有某种颤动动画或 ProgressBar 的模式对话框,以及一个取消按钮。重绘是有限的,因为您只绘制了新对话框的大小,并且由于对话框是模态的,因此阻止了对应用程序其余部分的输入。此外,当您有某种状态更新和/或动画时,用户更愿意等待,因为看起来计算机正在“工作”。
However, if there are operations your user can do while your web service request is running, it's better to leave the controls accessible. At very least, there should always be a way to interrupt/abort the process.
但是,如果您的用户可以在您的 Web 服务请求运行时执行某些操作,最好让控件保持可访问性。至少,应该总是有一种方法可以中断/中止该过程。
Update: Since you now changed the question: How long is it taking to construct the modal dialog? Why not simply construct the dialog empty, and then populate its controls? If all you have is a small dialog box with a single button and a single ProgressBar, then calling dialog.ShowDialog() should happen faster than your user can interact with your UI. Is that not the case?
更新:由于您现在更改了问题:构建模态对话框需要多长时间?为什么不简单地将对话框构造为空,然后填充其控件?如果您只有一个带有单个按钮和单个 ProgressBar 的小对话框,那么调用 dialog.ShowDialog() 的速度应该比您的用户与您的 UI 交互的速度更快。不是这样吗?
回答by TLiebe
One thing you could try for keyboard input is setting the KeyPreview property of the form to True. This will pass all keyboard events to the Form object first instead of to the individual controls. Create an event handler for the KeyPress event of the form and in there you can set the Handled property of the KeyPressEventArgs to True to prevent the key stroke from being passed to any of the controls. If you're currently retrieving data from the web service, set the Handled property True otherwise set it to False and the key stroke will be passed to the controls.
您可以尝试键盘输入的一件事是将表单的 KeyPreview 属性设置为 True。这将首先将所有键盘事件传递给 Form 对象,而不是传递给各个控件。为窗体的 KeyPress 事件创建一个事件处理程序,您可以在其中将 KeyPressEventArgs 的 Handled 属性设置为 True,以防止将击键传递给任何控件。如果您当前正在从 Web 服务检索数据,请将 Handled 属性设置为 True 否则将其设置为 False 并且击键将传递给控件。
If someone has a good idea on how to handle the mouse input yet you're set.
如果有人对如何处理鼠标输入有一个好主意,那么您已经准备好了。
回答by bryanbcook
I'd typically create a LockUI() and UnlockUI() functions in my form that toggle controls and flip a local form field that acts a flag to indicate a long running process. This approach works really well if you use a command pattern.
我通常会在我的表单中创建一个 LockUI() 和 UnlockUI() 函数来切换控件并翻转一个本地表单字段,该字段作为一个标志来指示一个长时间运行的进程。如果您使用命令模式,这种方法非常有效。
As previously mentioned, you could toggle keyboard input by using the KeyPreview property of the form (as suggested by TLiebe).
如前所述,您可以使用表单的 KeyPreview 属性来切换键盘输入(如 TLiebe 所建议的)。
As far as mouse input is concerned, you could disable mouse activity by hooking the WinProc messagesand intercepting mouse input messages. This is basically what KeyPreview does.
就鼠标输入而言,您可以通过挂钩WinProc 消息和拦截鼠标输入消息来禁用鼠标活动。这基本上就是 KeyPreview 所做的。