Why does my form sometimes vanish when closing a dialog? - c#

Occasionally, seemingly randomly, when I close a dialog form my main form seems to move back in the window order, disappearing behind the next application back (usually Visual Studio). It retains focus, so clicking it in the taskbar minimises it, requiring another click. Whenever this happens, the control colours seem to change a little as well, but revert if I maximise and restore the window.
Any idea why this happens?
Edit: This happens when I'm debugging; it might happen at runtime too, but I usually don't have anything behind the application then, so I haven't noticed. Nobody has mentioned it.

This will happen when the dialog closes and Windows cannot find any window in your app that isn't disabled. Forced to move the focus somewhere, it will pick a window of another app to give the focus to. Your form will disappear behind it.
Exactly why your main form is disabled when this happens isn't clear. The color change certainly suggests you are changing the Enabled property of the form. Everything turns battle-ship gray when you do that. Setting Enabled back to true after the dialog closes doesn't work, it's too late. Just don't tinker with Enabled, the ShowDialog() method already disables other windows.

Related

Winforms ShowDialog(this) blocks the switching windows of other applications to the foreground

When I open any dialog in my Winforms application then Windows 10 behaves oddly in these ways:
ALT-TAB no longer displays the list of windows
I cannot switch to hidden applications using taskbar icons - if I select a taskbar icon of a window that is not currently visible (even if it is not hidden by the winforms app) the icon just flashes and then stays highlighted, but is not brought to the foreground. I can use other applications that are visible. As soon as I close the dialog form the other I can use the windows of other applications correctly
If I switch to the application window that is behind the winforms application by clicking on it, I cannot go back to the winforms app either by ALT-TAB or by clicking on the taskbar icon. I can get back to it by minimizing the other application
I'm opening the dialogs with
dialogFormName.ShowDialog(this);
TopMost is set false on all forms and is not set in the code.
I've read about 50 related articles and the only problems seem to be either TopMost is set or ShowDialog is not called with the parent form. I'm not a regular Winforms developer so I'm probably doing something stupid. This is driving me crazy, so I'd really appreciate any help!
Edit: The same issues occur with MessageBox.Show(this, "test"). The issue does not occur with a newly created app just with a single button calling MessageBox.Show(this, "test"). The problem application uses EntityFramework but no other packages and the problem existed before I added EF.
After trying different scenarios I eventually found the issue. In my case I was calling ShowDialog() after a user clicks an item on a ContextMenu. The blocking of ALT-TAB was caused by the following code that attached the ContextMenu to the ListView that the menu was contextually for:
lstList.ContextMenu = myContextMenu;
As soon as I removed that association, the ShowDialog no longer blocked ALT-TAB.
Form.ShowDialog() blocks the parent form until it's closed.
Use Show() to display the form separately without blocking its parent.

Part of Control Ghosts After Close

I'm not sure how to explain this but occasionally I will experience an issue where I popup a dialog (say a file browser), and after it is closed, part of the dialog remains visible on top of my app. Sometimes if I minimize and restore it will go away.
Is this a common issue?
I have only ever seen this where the window that you are over stops responding and cannot update the area which has been revealed. However as soon as it does respond again then it redraws.
Maybe you could repeat this test and not minimize the window behind?

UAC Window On Top

I seem to be running into a dead end here. I have a project that does the following:
just runs and stays in notification area
when user presses middle mouse button, it shows a form
user can then chose whatever from the form, and be happy.
This is working just fine, however what is NOT working is that when the form is shown, it does NOT activate.
Now, prior to me modifying the app.manifest to requireAdmin, it was working fine. Any time the form was shown, boom it was active.
But now that i'm running the form as Administrator, given that I need to be able to control one of our other applications with it (that is ran as admin as well), the form comes up just fine, but doesn't activate.
I have tried:
- TopMost = true inside of the Form_Load method
- Calling SetForegroundWindow with the forms handle on Form_Load
- Calling ShowDialog both on Form_Load and also tried it when the form was built.
- Calling Activate on Form_Load as well as when the form was built
Here's my layout:
Program runs, requires UAC permissions due to the manifest, user agrees, and it kicks off
Only a notification icon appears, shows a nice little bubble saying it's running
Program.cs monitors the keyboard/mouse hooks
When middle mouse button, or any of the keyboard hooks are triggered, it creates a new form object
sets the location of where the form should appear
and then finally shows the form.
Again, without UAC and requireAdmin inside of the app.manifest, this works fine. But once it is running as admin, nope, wont stay in front.
I know that MS has made the SetForegroundWindow requirements much stricter with later versions of windows (Vista, 7, 8), but i really need to be able to make this form show as the top most, active window (like a context menu).
How can i do that properly?
You could split your program into two, a non-admin requiring half that sits in the tray and watches for the middle button, and the half that requires admin permission that you launch when the mouse button is pressed. The non-elevated half could then call SetForegroundWindow or AllowSetForegroundWindow as needed.
If you want to avoid a UAC prompt every time you can cache a COM elevation object via the CoCreateInstanceAsAdmin method and use it repeatedly.

Really annoying bug with TopMost property in Windows Forms

I have this Windows Forms application where it sits in the notification area. Clicking on the icon brings it up front, clicking it again (or clicking on the app X icon) sends it back. This is the type of app that having the window always on top is important when it's displayed by clicking the icon (it's optional though).
Right-clicking the icon brings up a context menu where one can select to enable the "always on top" option or not. When the application first starts up, the app settings are read from an XML file and I'm 99% that this is working as it should, the TopMost property is properly read (and written).
After some time (minutes, hours, days, whatever; I normally hibernate and rarely shutdown) the TopMost stops working. I don't change the option, I don't think anything is changing the option value but I click the notification area icon and app is not brought up front. It shows up but it's on the background (it displays on Alt+Tab), it's not "always on top" as it should. I bring up the context menu, disable the option (cause it's enabled) and enable it back and it starts to work after that. The app is now "always on top". However, it can lose this ability anytime after a while.
I can't understand why this happens and how this happens. Does anyone have any idea why? If not, any idea how could I try to debug such behavior?
EDIT:
I added a piece of code to show a MessageBox when the TopMost property was changed to see if I could notice any strange behavior but it was no good. It didn't help because the form was with TopMost = true but it still was in the background...
There is more than just one "Topmost" window. Topmost just says "Before all non-topmost windows".
I am pretty sure a reinitialization of the desktop (such as when hibernating) requires another SetWindowPos(hwnd, HWND_TOPMOST, ...) (which is the underlying Win32 API call).
As a workaround, you could reset and set the property again when showing the window.
Another possibility is that hiding the window also changes the Z order - either implicitely how Win32 implements that, or explicitely in the way WinForms call the hide/show window.
Like peterchen i also don't have a clue how to get the root cause. But why not make it a little bit simpler?
When you click on your Icon you'll show up your window and rely that TopMost is still active. Why not call SetWindowPos() with the current setting right before you show the window. This shouldn't make any performance problems (only happens if the user clicks the icon) nor any other side effect.
I know, it would be great to find out the root cause, but maybe it's not worth if you can solve it with such a little workaround.

Question about an application not getting focus in XP/W2K3

I have an application written in .NET. The previous version had no problems: you double-click on the icon or run it from a command line and when it starts up, it's the main window and has focus as you'd expect.
The latest version displays a splash screen before the main window and now the splash screen comes to the foreground ok but the main one does not always end up the main window. Sometimes it does, sometimes it doesn't. (When launched from the command line it invariably doesn't). When the main window does not come to the foreground and get focus, the taskbar icon shows as a steady orange.
I see lots of hits on the net about how MS added a facility to prevent applications stealing focus from others, centered around the ForegroundLockTimeout registry setting and related settings, but the behaviors described above for the different versions happen on the same machine.
I have tried called Activate in the main form when it finally gets created, and also SetForegroundWindow, all to no avail.
Any help is appreciated.
You should probably have the splash screen set focus to the main app window as it is going away.
As far as Window's knows your splash screen IS your app since it's the first toplevel window shown after the process is started. So that window gets the focus, but any OTHER window trying to grab focus on that same app startup (the icon click/run command) is believed to be a focus thief.
You can get around this by having the window that Window's believes has a right to have focus be the one to transfer focus to a new window.
So you splash should SetFocus on the main window BEFORE the splash is destroyed. If you destroy the focus window, then the focus is nowhere, which is probably what is happening currently in your app.
Sounds like your main window doesn't always get the focus back from the splash screen. Have you tried simply calling SetFocus in the main form's OnLoad handler?MSDN
I just corrected a similar problem. Just make sure your splash screen closes after your main form as shown (it will show in background of the splash if your splash is "always on top").

Categories