Jim Clark
Jim Clark

Reputation: 343

How do I block all keyboard and mouse input to my WinForms app?

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.

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.

Upvotes: 2

Views: 6784

Answers (4)

bryanbcook
bryanbcook

Reputation: 18393

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.

As previously mentioned, you could toggle keyboard input by using the KeyPreview property of the form (as suggested by TLiebe).

As far as mouse input is concerned, you could disable mouse activity by hooking the WinProc messages and intercepting mouse input messages. This is basically what KeyPreview does.

Upvotes: 0

Daniel Pryden
Daniel Pryden

Reputation: 60997

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".

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.

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?

Upvotes: 3

TLiebe
TLiebe

Reputation: 7996

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.

If someone has a good idea on how to handle the mouse input yet you're set.

Upvotes: 2

Nikolay R
Nikolay R

Reputation: 957

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.

Upvotes: 4

Related Questions