I can't get a form to remain on top, in .net
I have checked How to make form always on top in Application and the answer there mentions form1.TopLevel = true; and I've checked How to make a window always stay on top in .Net? and it says Form.ActiveForm.TopMost so i've tried Form.ActiveForm.TopMost = true; and this.TopMost = true;
private void Form1_Load(object sender, EventArgs e)
{
this.TopLevel = true; //default anyway
Form.ActiveForm.TopMost = true;
this.TopMost = true;
}
But as you can see, a notepad window or any window can cover it.
Added
I have tried every suggestion made so far.
In response to Han's advice, "Of all the possible places to set TopMost property, the Load event is the worst. It should be set in the constructor, so the window gets created top-most right away. Or it should be set after it is visible, so after the Load event. Use the constructor. ". I tried putting those lines in the constructor.
public Form1()
{
InitializeComponent();
this.TopLevel = true; //default anyway
//Form.ActiveForm.TopMost = true; (commented to prevent a System.InvalidOperationException, presumably the form isn't yet active at this stage)
this.TopMost = true;
}
And the the other two suggestions, from others-
I tried setting the Form's TopMost field in the designer to True.
And running the EXE directly rather than just clicking play in visual studio.
Same issue.
And if you find that hard to believe, i've taken a 1min video here showing just that. https://screencast-o-matic.com/watch/cbXXrw2oTN
A potentially useful comment was mentioned..
Steve comments - "OK something definitively odd is happening here. I have tried to create a simple topmost form using linqpad and at the first run I get your same behavior. At the second run though everything works as expected."
A workaround, is this, following on from Han's point to put not put it in Load. Load is indeed too early. I've been finding that (at least on the system with the issue), The Constructor is also too early. I find that putting it in the Shown event, works.
One possible solution to this, is to run this patch, https://support.microsoft.com/en-us/help/2587473/topmost-windows-are-not-always-in-the-topmost-position-in-windows-7-or But be warned, if you want to uninstall it, I have some doubts whether it uninstalls correctly. And it's also not clear to me whether the patch is working or working sporadically. It likely works but it's hard for me to tell.
One commenter thought it's just my system, though that's not the case, as Steve ran into the same issue the first time he ran it. I find it may be most prone to happen after windows restarts, So, the program is running very fresh. But I find that putting that code in the Shown event, is fine and the form stays on top.
I tried instead of TopMost=true, using SetWindowPos, to set the window on top, I tried it fairly early like in the constructor, and late, like in the Shown event or on a button click, and I found it was fine in the Shown event or on a button click. So the issue was related to the TopMost=true line, or SetWindowPos line, firing too early, prior to the window it is setting appearing.
When calling SetWindowPos later one can use either this.Handle or GetForegroundWindow(), the former is easier as it's native. When calling it earlier one must use this.Handle. And using this.TopMost=true avoids all winAPI calls completely.
So in short, you could try the patch, though note that it might not uninstall right.. Or you can try the workaround of putting this.TopMost=true in the Shown event of the form.
I'm having a problem focusing on a Control within a Window in WPF.
On the constructor of the Window I add a TextBox as follows:
TextBox tb = new TextBox();
tb.Text = input;
tb.SelectAll();
tb.Focus();
I also call the Focus() method again on the Window loaded event.
The problem is that sometimes the window focuses and other times it does not! This is very strange behavior and I was wondering if someone has had the same problem and might be able to give me some guidance.
-- UPDATE
I have found what is causing the problem but no solution yet. I am using WIA to scan a document, this brings up a ProgressBar which makes my entire application lose focus.
I have tried calling Application.Current.MainWindow.Focus() but this does not restore focus, any suggestions?
From memory, I think the last call on window creation is the Windows.Activated event. You could try running your focus code on that event?
Like I mentioned in my updated question my entire application loses focus due to another dialog being displayed, what I ended up using was:
Application.Current.MainWindow.Activate();
This returns focus to my application and when my Window with the TextBox is shown, Focus is applied to this control.
Hope it helps someone!
Please do not close the question straight away. The almost similar problem is also discussed in the following threads.
Windows Forms and ShowDialog problem
Form.ShowDialog() or Form.ShowDialog(this)?
But, these do not solve my problem.
The problem never occurred in my development machine. It occurred in the user machine but not always. In fact it occurred only 3 or 4 times.
When it happens it seems the application/calling form is frozen. If I can guess (as I am not seeing it on the screen) where the close button is and click on it on the called form, it closes and application goes back to usable state until it occurs again.
My views are encapsulated within the presenter, so I am not calling ShowDialog() from within the view but through the presenter.
MainPresenter
{
MainPresenter(IMainView view)
{
_view = view;
}
…
…
OpenSecondView()
{
var secondPresenter =_presenterFactory.Create<SecondPresenter>();
secondPresenter.Ininialize(_view);
}
}
// Initialize method in the SecondPresenter
Initialize(owner)
{
_secondView.ShowDialog(owner);
}
I am using observing presenter style of MVP explained here
http://www.aspiringcraftsman.com/2008/11/23/model-view-presenter-styles/
Questions:
How can I reproduce the problem in my development machine and fix it?
If I use Show() and set TopMost = true, is it possible this problem
to occur?
What are the things I should consider that may cause this problem?
If Show() absolutely guarantees that the problem will not occur, I will go with Show(). I kind of lost faith in ShowDialog() on this.
Any help will be greatly appreciated.
** The problem does not occur for a specific screen/view. It occurs randomly.
** For all the forms except main form, ShowInTaskBar is set to false.
You can try using TopMost = true for the form
Have you tried adding a this.Activate() in the load event for the form, because I have had a similar problem.
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 have a very strange behavior that only seems to happen on one form.
Basically I am creating an instance of a Form, and calling Show() to display the form non-blocking. In that form's Load event handler, I have some logic that may call this.Close() under certain circumstances. This closes the form, but then the form Show() method in the client code throws an ObjectDisposedException.
The stack trace from the ObjectDisposedException is as follows:
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Form.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.ContainerControl.FocusActiveControlInternal()
at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
at System.Windows.Forms.Control.Show()
...etc.
This is what I'm seeing happen:
Control.Show() is called
my form is launched
the OnFormLoad method is called
the FormLoad event handler is called, inside of which I call this.Close()
the OnFormClosing method is called
the FormClosing event handler is called
Dispose is called on my form and all it's user controls
and then somewhere toward the end of the Control.Show() method, it tries to get a handle to the form, which freaks out and throws an exception because the object is marked disposed.
My real question is, why can I do this exact same thing on every other form I have without exceptions? Is it a GC issue? I've tried putting a GC.Collect() call right after the this.Close() and it makes no difference. Like I said, it happens 100% of the time on this form, and never anywhere else, regardless of child user controls, scope of the form variable, etc.
Any ideas?
The best way to do so :
this.BeginInvoke(new MethodInvoker(this.Close));
this is the most simple way you wont get ObjectDisposedException
I know this is an old issue but no one seemed to have posted the obvoius answer.
You say you call Control.Show() and then Form.Close() and then the form is Disposed of. Well, unless you use MDI or use ShowDialog that's just as documented. Though, the short version of the Close() documentation is "Closes the form", it actually also disposes it implicitly under certain conditions.
See the remarks section:
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx
If you want to show a form again. Use the Hide() method instead of Close().
Hope that helps other searching souls.
And guys, don't stop searching at "I don't know why it works sometimes". That becomes buggy software with lots of defensive "I'll call this method again just in case" stuff. Not good.
Ok, hate to answer my own question, but this was driving me nuts, and it was one of the hardest bugs to reproduce I've ever seen.
On my form I'm overriding the OnFormLoad and OnFormClose methods, where I save/restore the form's Size, Location, and WindowState to/from the registry. I took this code out and it fixed the problem. The weird thing is, I put it back and the problem didn't come back.
I finally reproduced the problem: you have to let the form open fully, maximize it, and then close it so that the Maximized state is saved to the registry. Then when you open it again, it will set it to Maximized, and if it closes in the Load handler, it tries to access the Size/Location as it's closing. Apparently accessing these values in the OnFormClosing method causes the form to try to focus IF AND ONLY IF the form is maximized, which is illegal, since the form has been disposed.
So basically, you can't access Form display properties in the OnFormClosing method of a form, if that form is going to call Close from it's Load event.(Unless you check the Disposed prop first)
pretty specific piece of Winforms wisdom I know, but I'm writing it down anyway.
If you want to close a form as if the user pressed the cross in the upper right corner (usually means cancel), just add the following code.
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Close();
This also works in the form load function:
private void MyForm_Load (object sender, EventArgs e)
{
// do some initializations
if (!ContinueLoadingForm())
{
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Close();
return;
}
// continue loading the form
}
If you don't want the form to be visible for a short while, set the Visible property false (for example in the designer or constructor), and set it back to true when you are certain the program can continue loading.
In load event is not realy good idea close the form. Do it after the Activated event.
protected override void CreateHandle()
{
base.CreateHandle();
if (FormMustClose) //FormMustClose is a variable in the loadevent.
{
Close();
}
}
One possibility:
They may have a timer on this form, that is being initialized and enabled in their FormLoad event. The timer would need to be disabled and stopped as well, before the form was closed, if the timer is trying to access the form when it's fired.
I've seen forms before that do this...
It seems to me, without looking closely at it, that the cleanest way to accomplish what you want might be to make a custom form class deriving from Form, and override OnFormLoad(...) and/or Show() to check for your condition and cancel out early.
That said, I don't know why it would work sometimes and not other times.
Have you tried stepping into the .net code to see what line of code is being called when the exception is occuring? If you have VS 2008 you can do so by going to Tools --> Options --> Debugging and select the Enable .NET Framework Source Stepping. Be warned, this may take a while to download all of the necessary files, but this way you can step into the form.Show() and see exactly what is going on.
Ok, it turns out it's a little simpler and more generic than I thought, but still weird and obscure.
If you're saving/loading the form Size/Location/WindowState when the form loads/closes like we do, you have to make sure that the OnLoad method calls base.OnLoad first so that the Form Load event handler fires, and THEN set the properties. Not doing so will only cause a problem if the form calls Close from inside the Load method. You'll get an ObjectDisposedException on the Show call after the form closing event is done.
My head hurts.
Form.Shown() Is the trick too.
As I understand it, setting the DialogResult of the form will close the form - may have to be other than DialogResult.None. (i.e. you don't need to then call the Form.Close() method).
The issue is also in part that if elsewhere in code, you are accessing a property of the form or control within it, that may prevent the form from closing.
It may also be best if as has been suggested, you have a property e.g.
private bool _loadedOk = false;
in your form which you set in your initialisation code. In one of the later events after Form_Loaded, you then interrogate this and close the form if it's false.
Perhaps someone can suggest the best event to do this in??
If you want to close the form without flicker, the best way I found was override SetVisibleCore Method:
public partial class MyForm : Form
{
...
protected override void SetVisibleCore(bool value)
{
if (value && !IsHandleCreated && !ContinueLoadingForm())
{
base.SetVisibleCore(false);
this.Close();
return;
}
base.SetVisibleCore(value);
}
}
Then you can simply do:
...
var myForm = new MyForm();
myForm.Show();
...
The Form only will appear if ContinueLoadingForm() be true, this works with ShowDialog() and Application.Run() as well.
Expanding on RCMAN's answer in this thread (which got me 99% of the way to the finish line) ...
Here is the code I ended up using which also avoids the screen flicker:
Me.FormBorderStyle = FormBorderStyle.None
Me.Opacity = 0.01
Me.MinimumSize = New Size(1, 1)
Me.Size = Me.MinimumSize
Me.Location = New Point(1, 1)
BeginInvoke(New MethodInvoker(AddressOf Me.Close))
Additionally, to avoid the message "This program might not have run correctly" I applied a manifest change as described by mik here:
How to prevent "This program might not have installed correctly" messages on Vista