0

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:

  1. User runs my application and opens a modal window.
  2. 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.
  3. 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?

Community
  • 1
  • 1
sventevit
  • 4,766
  • 10
  • 57
  • 89
  • 1
    Hmm, is it intentional that the task bar showing both the icon for the main window as well as the modal window (dialog)? This sounds like the dialog is not owned by the main window. If you make the dialog being owned by the main window, the dialog will never be covered by the main window. That also has the effect that when bringing the main window to the front the modal window will also be brought to the front. (Check the [Owner property](https://msdn.microsoft.com/en-us/library/system.windows.window.owner(v=vs.110).aspx) of your modal window. It should be set to the main window.) –  May 20 '17 at 19:22
  • @elgonzo - you are correct, I forgot to set the Owner property, thanks! If you post your comment as an answer I will accept it. – sventevit May 20 '17 at 19:36
  • It's done... :) –  May 20 '17 at 19:54

2 Answers2

1

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.)

  • 1
    As said before - your solution works. Just a nitpick though - even if you set the Owner property you can still see both main window and dialog when you hover over the icon on the taskbar. But id doesn't really matter which window you click, the modal one is always on top. – sventevit May 20 '17 at 20:09
  • 1
    @sventevit, Haha, you are right. The modal window would normally show in the taskbar. If this is not desired, ShowInTaskbar has to be set to false. Which i do habitually. Guess i confused my habits with the habits of WPF :) I'll rewrite the affected parts of my answer in a moment... –  May 20 '17 at 20:20
0

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.

Gururaj
  • 539
  • 2
  • 8