I have a form which I would like to block during execution of an async event. I would like to achieve an effect similar to when a dialog window is displayed, without displaying or creating one.
I don't want to manually disable controls on the form, as some controls may be added in the future (not necessarily by me). I would like to avoid disabling the entire form / user control for aesthetic reasons.
Is there a standard/elegant way of achieving this, or am I going in a wrong direction?
You can block WinForm window by setting it's Enabled property to false, but it will prevent user from any action with that window (like moving, resizing or hiding) and it may be very annoying. Consider showing some load indicator instead.
I would not recommend to disable controls without making them look disabled because it could confuse user.
Edit: As #AvoNappo pointed out window behavior differs depend on where to set Enable property to false:
if you set it in the constructor user still will be able to move/minimize/close window;
if you call it after constructor window control buttons and windows movement also will be blocked.
Related
I want a form to be shown modal every time it is opend. Since I can not change the way it is created and opend. I wondered if it is possible to make the form stay on top from within the forms class.
One opportunity is the TopMost property. This works in general, but if I display the form while the main thread is waiting for it to close, the form will stay on top even if I change the application(to a browser for example). So no matter where I am, the form is still displayed.
Another issue which I came across is that in some cases it is adopted by the parent form which then might block other windows or popup messages.
I was thinking about a hook to the OnLostFocus event to get it on top again, once the focus is lost, but I'm not sure if that is a good idea ...
Any helpful thoughts about it?
Edit
Due to the comments I will extend my description, Here is the real use-case
We are using the Devexpress's SplashScreenManager which is able to show a certain form as a WaitForm. Since the WaitForm is not intended to be shown modal(see on the Support Center), we are looking for a way to do so.
We can not change the way the form is shown, because this is done through the SplashScreenManager. The WaitForm is shown both from the main thread, as well as from certain backgroundworker.
So this is only about an own form of ourselfs, displaying it within our own application.
Use:
TopLevel = true;
This will do exactly what you want; be topmost as long as the main form is shown and hide if the mainform is hidden by another window.
You can set the owner of your splash form to your main form explicitly without using .Show(owner).
splashForm.Owner=mainForm;
splashManager.Show(splashForm);
We did not want the TopMost property since it works on windows level and covers other windows too (for example the browser).
In the end I hooked up on the focus event of the window to make sure the window is always on top.
I have a WinForms application that, at some point, will do some calculations that take a couple of seconds. During this time, I disable the controls. Additionally I want to display a popup that kind of 'blocks' the application more visibly.
I tried placing a Panel on top of the Form in order to do so, but there I'm somehow not able to add any text to it. I.e. the Labels and ImageBoxes I put there are somehow not displayed or behind the Panel.
Any suggestions how I could achieve this in a quick and easy way? .. I mean, without redesigning the whole Form.
Your problem with the things not showing up in your additional panel is that everything is happening in the same thread, but your calculations are blocking everything from appearing because they are hogging up the thread. You should look into using a backgroundWorker, which is one of the tools in WinForms. You should throw the function call that performs the calculations into the DoWork method of the backgroundWorker, then the form itself can continue to function during the calculations.
See http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx for examples
Create a Dialog Box (windows form) to popup during the processing, then you can have the Dialog Box close once your processing is completed.
By using a Dialog Box not a Message Box, you can still have control over closing the window when your processing is done.
You could create a simple UserControl with just a Label and an ImageBox, maybe with public setter for their values. You can add it to your form setting its Visible property to false. Then you can make it visible during your calculations and go back top invisible in the end.
I was wondering if there are any gotchas for making a form completely transparent (as opposed to hiding it). For instance, I know that these are things that got my by surprise when hiding a form:
If a form is hidden, you cannot interact with its controls (can't add HTML to a webbrowser control, can't push a button, etc.)
Changing the WindowState (minimized, maximized, etc) of a window while it is hidden will cause the window to appear outside the scope of your work area when the form is shown again.
Has anybody run into similar problems (or completely different ones!) while using a form with opacity set to 0 (completely transparent)?
If you don't need the form anymore, hide it.
But if you still have a task or timers running in the form you want to keep, or you want to keep the user's input, then you'd do good to set the opacity to 0%.
This is what I do when I want a form to be hidden, but still active:
frmMain.Opacity = 0; // To make it invisible.
frmMain.VisibleInTaskbar = false; // To make the taskbar entry of the form disappear, and to make sure that the WindowState isn't changed.
frmMain.Enabled = false; // To make sure the user doesn't type something in the form, or presses a button (by pressing enter) by accident.
From the up votes for my comment, I guess I'll submit it as an answer. I would discourage using Form.Opacity = 0. Even though you can disable the form to prevent accidental interaction, I would think the transparent form would overlay other windows and confuse the user as to why he can't interact with windows behind your transparent one.
As for the gotcha's for Form.Hide(), I typically queue form responses so that when the form returns into view (or visibility), it goes through the queue to process actions (i.e. changing FormState). Changing the form while it's hidden can also really confuse the user.
This is a very similar problem to This one, sadly that one was never answered either.
I have a MDI Main forum that hosts several children forms. One of them does a long calculation and throws an exception if an error occurs (all work is done on the same thread). I then try to inform the user of an error with an messagebox, however it doesn't appear (but steals focus from the MDI Main, so the application is completely unresponsive).
The beheviour changes slightly if I call Application.DoEvents() (evil I know, but this is a last resort thing). Then the forms remain completely active and the messagebox only appears after I change active application (Alt+Tab) to something else and then back again.
What can I do to make sure the messagebox will be visible? I have already tried passing both, active child and MDI Main as parameter to the MessageBox.Show method. It doesn't change the behaviour.
To clarify: the messagebox is a part of the child form, however at this point I am willing to show it in any way that doesn't break the application. The messagebox should be modal, but it should be visible so it can be acknowledged by the user.
I had the same issue. When pressed ALT the popup showed.
It turned out to be a LinkedLabel that had the AutoSize property to true. The LinkedLabel was inside a FlowLayoutPanel. When I set the LinkedLabel.Text property to String.Empty. The LinkedLabel constantly tried to resize, which was causing the GUI to be constantly busy.
When I turned off the AutoSize property and the GUI no longer had to recalculate the positions. The GUI was no free. And the popup showed.
There could be other controls that are behaving the same.
See also:
https://connect.microsoft.com/VisualStudio/feedback/details/116884
Is the MessageBox shown in the MainForm or as part of the ChildForms? If the MessageBox is in the child Forms maybe you could pass an event back to the MainForm and open the MessageBox there.
The problem is that messageboxes tend to be modal.
In this instance I think that you'd do far better to use a delegate or an event with a handler in your main MDI code. That way your main application displays the message boxes. You can easily redefined an EventArgsType if you wish to pass whatever information that you require.
I am developing a touchscreen friendly app that also includes a virtual keyboard. My virtual keyboard is in its own window, allowing it to be moved around. The problem is that when I click on a key on the keyboard the text box on the main application window no longer has focus. The switch from the main application being the active window to the keyboard dialog being the active window means that any field on the main window no longer has focus. How can I get around this?
I tried setting the keyboard window as not focusable. Though this is probably good to set, it did not solve my problem.
You could just return focus to the original window asynchronousely:
public static void BackgroundFocus(this UIElement el)
{
Action a = () => el.Focus();
el.Dispatcher.BeginInvoke(DispatcherPriority.Background, a);
}
But this is not ideal, because the original window caption would flicker when losing focus...
Why don't you use Popup instead?
Check out the function SetForegroundWindow() ,
I have used this long time back some where in my project
May be this may help you
Using a Popup, as already suggested, seems like a good solution. As for your custom window, try setting the Window.ShowActivated to false.