I'm developing an UWP app that surrpots multiple windows like Microsoft Edge or Sticky Notes.
I succeeded to close child window by caling Window.Current.Close(), but cannot close main window, or the base window of child windows.
Exception thrown: 'System.Runtime.InteropServices.COMException' in MyApp.exe
WinRT information: Closing main window is not allowed.
On the other hand, we can run Microsoft Edge windows and close them regardless of the order.
Is there any way to close main window or change parent-child relationship of windows?
Execute ApplicationView.GetForCurrentView().TryConsolidateAsync() in main window to close it properly as if you have closed it by clicking close button in title bar. If your app has only one window per instance you should prefer this over Application.Exit() as this method suspends the app while Application.Exit() closes app abruptly. Also closing app by this method your app's previous position and size is remembered unlike for Application.Exit().
Related
I've ran into a weird bug where a WPF app is closing after the first window closes. This has made me curious what is triggering it to close
For example this is what I was the unworking version. After the EULAWindow would close it would shut down the application.
EULAWindow eula = new EULAWindow();
eula.ShowDialog();
MainMenuWindow mainWindow = new MainMenuWindow();
mainWindow.ShowDialog();
I thought it would open the EULA and then open the Menu window. I've found that if I rearranged the code it will operate like expected.
For example this will fix it:
EULAWindow eula = new EULAWindow();
MainMenuWindow mainWindow = new MainMenuWindow();
eula.ShowDialog();
mainWindow.ShowDialog();
This brings me to the question of what actually is causing the application to shut down in the first situation?
ShowDialog() is a blocking call. So, in the first case you have single window, then show it, then let user to close it. What should an app to do once last UI window is closed? Maybe, follow to app shutdown code? I suspect so.
In the 2nd case you create two windows before the blocking inside ShowDialog(). So, once you closed the first window, there is another one that could accommodate the user, and the app is not shutting down, it just waits for the next window to be shown.
Since I was using Application Startup to create my windows, it was defaulting setting the EULAWindow to the Current.MainWindow Then keeping the Current.ShutDownMode as ShutdownMode.OnMainWindowClose.
When you create two windows, before calling Show or ShowDialog, it changes the shutdown mode automatically to ShutdownMode.OnLastWindowClose
I'm not certain how or where this happening, but I can tell this is the behavior that is happening upon further investigation.
I want to prevent users to run my application multiple times on the same machine so I used a solution from this thread: What is the correct way to create a single-instance application?
This works OK, but I have a problem displaying my application when a modal window is opened (for example with view.ShowDialog();). This is a scenario:
User runs my application and opens a modal window.
Then he tries to run my application again, the code in the startup procedure of this second instance of the application finds another application running and broadcasts a WM_SHOWME message to it to show it self. Then the second instance of the application terminates.
The first application receives the WM_SHOWME message (using the solution from How to handle WndProc messages in WPF?). Now it should bring the topmost window to front, and this is my question - how can I get the topmost window of my application if the topmost window is modal and not even active? I tried with the solution from Refer to active Window in WPF? but of course my windows aren't active so this doesn't work.
PS - when the application is running and a modal window is opened and when I hover over the icon in the task bar, then I can see two windows - main window and a modal window. I can click on the main window (which is of course disabled because a modal window is on top of it) and I can click on the modal window also. My solution works just like if I would click on the main window, but I want it be able to activate the topmost window, which is modal in this case.
So, any idea how to bring the topmost modal window (or main window if no modal windows are shown) to the front?
The behavior as described in the question indicates that the main window is not owning the dialog.
Note that when a dialog is owned by a (main) window, then the window cannot cover the dialog (the dialog will normally always stay on top of the window).
This also has the effect that when bringing the window to the front, the dialog will also be brought to the front on top of the window -- which neatly will solve the problem you have.
Setting the owner for your dialog (modal window) is rather easy. Simply set its Owner property to you main window before showing the dialog, similar to this example:
Window modalWindow = ... create modal window instance
modalWindow.Owner = mainWindow;
modalWindow.ShowDialog();
(Side note: If it is also desired to have only the icon/thumbnail of the main window appear in the task bar, then the ShowInTaskbar property of the modal window should be set to false.)
The best solution to make your application a single instance on a give machine is to use Named Mutex
Mutex
Here's the excerpt from the same documentation
Mutexes are of two types: local mutexes, which are unnamed, and named system mutexes. A local mutex exists only within your process. It can be used by any thread in your process that has a reference to the Mutex object that represents the mutex. Each unnamed Mutex object represents a separate local mutex.
Named system mutexes are visible throughout the operating system, and can be used to synchronize the activities of processes.
You can create a Mutex object that represents a named system mutex by using a constructor that accepts a name. The operating-system object can be created at the same time, or it can exist before the creation of the Mutex object. You can create multiple Mutex objects that represent the same named system mutex, and you can use the OpenExisting method to open an existing named system mutex.
And, anyways you've handled the case where you want to bring the first instance forward.
Why is it that if I call a WPF form from another project type (e.g. a console application or XNA game), the main application doesn't wait for the form to close before ending (and subsequently closing the form)?
I know with a dialog box I can make the main class wait for a reponse, how can I make it do that with my form?
You can open the window in modal mode using the ShowDialog method - the ShowDialog method only returns after the window was closed. Otherwise you can either wait until the Closed event is fired or wait until Application.Windows collection is empty (meaning the application has no WPF windows left).
For more information about window closing in WPF, refer to this.
Goal:
Enable closing of the application's window(s) independently without affecting others. The application is created in WPF.
Problem:
Can't close the window(s)
In winform, it is enough to have the code winform.close() to close down the window but it doesn't work in WPF.
You can have this code to close a specfic window:
Application.Current.Windows[0].Close();
but how would it work if you have many windows and you want to close a specific window without affecting the others?
Use the Application class to get the windows through Application.Windows-property exactly as you described. If you are in the code-behind of the window, call this.Close();
Configuration for multiple Windows
Set the main window to the Application.MainWindow property and set the Application.ShutdownMode to a appropriate value if you also want to hold the app open, if the main window is closed (e.g App.Current.ShutdownMode=ShutdownMode.OnExplicitShutdown; ).
I have already observed, that some people have had problems with the ShutdownMode. A workaround for this is to open the first window invisible and from this window, you open the visible application windows. This prevents the application from closing if the first created window will be closed. However you should be able to resolve this problem also over the ShutdownMode-property.
In scenarios with multiple windows, you can use Shutdown to close the app without closing every window.
I hope this answer is what your question is about. Make a comment if not.
I am agree with HCL. You can use this.Close(); from code-behind of the window, this will close WPF window as like winform.close();.
Or you can use following code for get the specific window for close
Window win = Application.Current.Windows.OfType<Window>().SingleOrDefault(w => w.Name == "Window Name");
win.Close();
just use this code to close the most recent window
Application.Current.Windows[Application.Current.Windows.Count - 1].Close();
I am starting an application in C# through Process.start(). when that application opens initially a child window runs to attempt to connect to a simulator hardware. till the child window succeeds in connecting to the hardware the child window remains in focus and the main window remains in the background. once the child window succeeds in connecting to the simulator hardware,i want to send key strokes to the main window. so i want to know the time lapse taken for it to connect to the hardware and also to capture the child window now. can anyone let me know how to do it if possible?
does Process.MainWindowHandle not suite your needs.