I am trying to use the SplashScreenService to show the user the progress of starting the application. Within the tasks I am creating the logger, the container, configuring the container, creating and initializing my MainWindow (View+ViewModel) and so on ... the tasks of a bootstrapper.
But the SplashScreenService refuses his work when committing because of Application.Current.MainWindow == null. The thing is that Application.Current.MainWindow is set within the initalization task.
I could workaround this with temporaly setting Application.Current.MainWindow = new Window() before the splashScreenService.Commit() and fixing the issue with MainWindow gets closed after SplashScreen is closed by setting the owner to null of my MainWindow (the owner was set to the PleaseWait dialog which therefor also closes the MainWindow).
So why must the Application.Current.MainWindow be set to get the SplashScreenService working? Within the service there is no code that uses this property. And I can only create my MainWindow after all other tasks are completed - a real chicken-and-egg problem!
Related
I'm using a Mutex to ensure that only one instance of the application is able to run at any given time.
I allow the user to close the MainWindow but I keep the application running with the ability to open another instance of the MainWindow by double clicking the Notify Icon in the system tray.
What I want to do is create a new instance of the MainWindow in the currently running instance of the application (the one that was started first), if the MainWindow is not currently opened, whenever the user attempts to run another instance of the application.
I've found that I'm able to restore a current instance of the MainWindow from another instance of the application by using the Windows API messaging system, but if the MainWindow is closed, the WndProc function naturally doesn't receive any messages, so I can't use that.
I also thought about calling Hide() on the window when the close button is clicked instead of actually closing the window instance, but I can't get the window fade animation to display when using Show(). From the other posts I've seen about the Show() function, the animation only displays the first time you show the window after it has been created.
Here's the code for my App.xaml.cs, if it helps:
protected override void OnStartup(StartupEventArgs e)
{
bool singleInstance;
mutex = new Mutex(true, UniqueMutexName, out singleInstance);
if (!singleInstance)
{
NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WindowsMessage.WM_INSTANCEATTEMPT, IntPtr.Zero, IntPtr.Zero);
Current.Shutdown();
}
else
{
// create the NotifyIcon if this is the only instance
NotifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
}
base.OnStartup(e);
}
In the above code, the window message just checks if the window instance is minimized and restores it if so. Any other ideas of things I could try?
suppose i have 2 windows: InputWindow and DisplayWindow
Currently:i want to use InputWindow to hold data via an App variable
// in InputWindow
(App.Current as App).u_id = obj.id;
where u_id is the object i defined in app.xaml.cs and obj.id is the input variable in InputWindow.
However when i close InputWindow and display DisplayWindow:
// in InputWindow
DisplayWindow window = new DisplayWindow();
window.Show();
Application.Current.MainWindow.Close();
The app also kill the data in the InputWindow.
So my question is:
Is there a way to keep the data via from the closed Window to the open Window?
Set Application.ShutdownMode to ShutdownMode.OnExplicitShutdown.
You can do this in you App.xaml, or anywhere else in C#.
<Application ... ShutdownMode="OnExplicitShutdown>
...
</Application>
Or in your App.xaml.cs:
ShutdownMode = ShutdownMode.OnExplicitShutdown;
Or somewhere else:
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
To shut down your application, you will need to call Application.Shutdown():
Application.Current.Shutdown();
You can also set Application.ShutdownMode to OnLastWindowClose, to shut down your application when the last window is closed (rather than when the main window is closed). You can do this in any of the ways described above.
However, it sounds like the only reason you want to keep your main window alive is so that you can use it as a data store. I recommend using a separate object as your data store, and referencing it both from your InputWindow and your DisplayWindow.
Application.Current.MainWindow.Hide();
You can hide the window using this line... or you can pass the information that you want to use into the new window using the constructor.
DisplayWindow window = new DisplayWindow(object myObject);
That constructor must have the information you want passed but this can solve the issue as well.
I have an application that has the start up window for the login, if the login is correct, it open the main window of the application.
When the login is correct, I open the new window in this way (I am using MVVM pattern):
PrincipalViewModel miPrincipalViewModel = new PrincipalViewModel();
PrincipalView miPrincipalView = new PrincipalView();
miPrincipalView.DataContext = miPrincipalViewModel;
App.Current.MainWindow.DataContext = null;
App.Current.MainWindow.Close();
miPrincipalView.Show();
In this case I don't set the new main window. Another option is this code:
PrincipalViewModel miPrincipalViewModel = new PrincipalViewModel();
PrincipalView miPrincipalView = new PrincipalView();
miPrincipalView.DataContext = miPrincipalViewModel;
App.Current.MainWindow.DataContext = null;
App.Current.MainWindow.Close();
App.Current.MainWindow = miPrincipalView;
miPrincipalView.Show();
In this second case, I set the main window property to the main window of the application, because the login window is closed.
But I don't see any difference in the behavior in both cases, so I am wondering what is really MainWindow and the use and meaning that is has.
Thank you.
In the first case you no longer have an actual MainWindow but that shouldn't be an issue unless you rely on the Application.Current.MainWindow property to return a valid reference to a window somewhere in your application or if you have set the Application.ShutdownMode property to OnMainWindowClose.
The default value is OnLastWindowClose which means that your application will shut down as expected when you close the new window anyway.
As the documentation on MSDN says "the lifetime of some applications may not be dependent on when the main window or last window is closed, or may not be dependent on windows at all.".
Here is part about what is App.Current.MainWindow from MSDN
MainWindow is automatically set with a reference to the first Window
object to be instantiated in the AppDomain. You can specify a
different main window by setting MainWindow assigning another Windows
object to the MainWindow property. If the ShutdownMode property of the
Application object is set to OnMainWindowClose, closing the main
window causes the application to shut down. It is possible to set the
MainWindow property from XAML, if an application's main window is not
the window that is produced by setting the StartupUri property in
XAML. The two limitations of the XAML approach are: You can specify
either a XAML-only Window or a XAML-only NavigationWindow as the main
window. You must set the Visibility property of the window you
specify, otherwise it won't be shown. The reference to the first
Window object to be instantiated is also added as the first item to
the Windows collection. If MainWindow is subsequently set with a
reference to a different Window, the position of the item with the
reference to the main window will change, while the order of items in
Windows remains the same. Consequently, always use MainWindow to refer
to the main window instead of the first item in Windows.
I think that you just need to set App.Current.ShutdownMode to ShutdownMode.OnExplicitShutdown before App.Current.MainWindow.Close(); and call App.Current.Shutdown when you will want to close the application.
MSDN Application.ShutdownMode
I have the following C# code in a WPF project:
private static void RunConfig(string owner)
{
long ownerHandle;
var settingsWindow = new SettingsWindow();
if (long.TryParse(owner, out ownerHandle))
{
WindowInteropHelper helper = new WindowInteropHelper(settingsWindow);
helper.Owner = new IntPtr(ownerHandle);
}
settingsWindow.ShowDialog();
}
The SettingsWindow isn't properly modal to the owner window (i.e. I can focus on, interact with, and even close the owner window while the SettingsWindow is still open). What am I doing wrong?
For context, this code is part of a screen saver program, and the owner window is the Control Panel screen saver selection window (which passes in the handle to use as owner via command line parameter). I know the IF statement is evaluating true and correctly parsing the handle.
I have also tried using the SetWindowLongPtr method from user32.dll (compiling for x64, hence not using SetWindowLong) which is briefly described here and shown in use here. This method works in WinForms, but doesn't seem to work here in WPF. Help me Obi-Wan Kenobi, you're my only hope.
It turns out that using WindowInteropHelper to set the native window as owner of the WPF Window does work, it just doesn't do the whole job. When set this way, the WPF Window will remain visible on top of the native window, even if the native window has focus. However, that is the only effect obtained. The WPF Window does not prevent interaction with the native Window, and the native window can even be closed, without the WPF Window closing or being affected.
In order to get the rest of the desired behaviour, we need to use the EnableWindow function in user32.dll to disable the native Window before calling ShowDialog on the WPF Window, and again to re-enable it once the WPF Window closes.
The modified code looks like this:
private static void RunConfig(string owner)
{
long ownerHandle;
var settingsForm = new SettingsWindow();
if (long.TryParse(owner, out ownerHandle))
{
WindowInteropHelper helper = new WindowInteropHelper(settingsForm);
helper.Owner = new IntPtr(ownerHandle);
NativeMethods.EnableWindow(helper.Owner, false);
settingsForm.ShowDialog();
NativeMethods.EnableWindow(helper.Owner, true);
}
else
{
settingsForm.ShowDialog();
}
}
(Note: The above code is correct in general, but incomplete in the case of screen savers, which is what this code is actually being used for. In the case that this code is being used for the config window of a screen saver, the string passed in for the owner handle is not the handle of the Control Panel window to be used as owner, but rather a handle for a control that is a child of the Control Panel window. The extra step in this case is to get the handle of the parent of that control. We can do this by calling GetParent, also in user32.dll, on the passed-in handle. This will return the real handle we want to use for the owner and EnableWindow calls.)
If anyone from Microsoft ever finds this, maybe consider modifying WindowInteropHelper to properly set all of this up when Owner is assigned and ShowDialog used, since this is the proper complete behavior for modal windows.
I have a form which instances a new form that I've already created using
statuswindow statwin = new statuswindow();
statwin.ShowDialog();
return statwin;
This code is in a function. The problem is when I run the function in other code the next line of code doesn't run until the newly instanced window is closed by the user, I'm guessing this is the side-effect of using ShowDialog(), is there a way to have it use the same behaver (being topmost, not being to select the other main window) while still letting the main form's code run?
Update: Although Show(); will work, I need to be able to make the window like a dialog by having it always on top of the other window and it always being the active selected window.
The ShowDialog method of showing a window shows it as a dialog, which is a blocking mechanism within C#/.net. If you want to simply display the window and not cause the running code to block until it is closed, you can use the window.Show() function.
In your code:
startwin.Show();
This will cause the startwin form to become visable to the user, and will fire the startwin.VisibleChanged event as well as the startwin.Load event to fire.
To make the new window always on top, you could set the Topmost window flag in the form properties.
To make the window run in a separate thread, first spawn the thread, then create the window from that thread.
There are also "application modal" and "system modal" Win32 window flags, but I don't know if those are exposed to WinForms or not -- go have a look on the form properties!