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.
Related
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.
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().
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();
Instance A is trying to restore instance B's window, but I can't get the B's window handle. I think the problem is that the window is being minimized by B to the system tray using:
this.Visibility = Visibility.Hidden;
And A is trying to get B's window handle using:
Process process = Process.GetCurrentProcess();
Process.GetProcessesByName(process.ProcessName).First().MainWindowHandle;
Which is equal to IntPtr.Zero.
I also tried to get the window handle by class name using Spy++ but the class name has a per-instance GUID in the following format:
HwndWrapper[FileName.exe;;ad445199-cf93-48a4-bd24-2f97d54c8af8]
That is because what you want basically doesn't exists, and the concept of MainWindowHandle is a gross misnomer that sneaked into the .Net Framework for everlasting confusion. From There can be more than one (or zero): Converting a process to a window:
"I have a thread ID. How do I get the
corresponding window?"
You can use the EnumThreadWindows
function to get all the windows on the
thread.
"Yes, I know about EnumThreadWindows,
but how do I get the window that I
want?"
Well, you haven't said what you wanted
yet.
"I want the window that corresponds to
the thread."
But which one? How will you decide
among all the windows?
"That's what I'm asking you!"
But you haven't yet described what you
want.
"I want the window corresponding to
the thread. Why won't you answer my
question?"
Note that saying, "I am looking for
the top-level unowned window" is a
step forward, but it still doesn't
uniquely identify a window. There can
be multiple top-level unowned windows
in a process. For example, Explorer
typically has lots of top-level
unowned windows. There's the desktop,
the taskbar, your open folder windows,
and property sheets. If you ask for
"the" top-level unowned window of
Explorer, which one do you want?
Perhaps people are getting the idea
that there is a way to uniquely
specify "the" window for a process
because the System.Diagnostics.Process
object has a property called
MainWindowHandle. The documentation
for that property doesn't do anything
to dispel the notion, either. I have
no idea how that property decides
among multiple top-level unowned
windows.
The topic is also elaborated in MSDN Q&A Get the Main Window:
Q How can I find the main window for a process? I'm writing a Spy-like tool and I need to get the main window (HWND) for a process so I can send it a message like WM_ACTIVATEAPP.
A Which main window do you mean?