Bring application to Front

I’ve written a full-featured Diary application. This works nicely (TextArea is sooo powerful…!)
However if I minimize it, and the User starts another one, there will be two running - I don’t want that.

When a new instance starts, I can easily check if there’s one already running (by shelling to TaskList), and get the PID.
But I want to go one step further, and NOT start another one, but just un-minimize the existing application, i.e. bring the existing application to the front.

How do I do that?

Note I have checked the database and there’s a number of older answers to this, but I still can’t find a straightforward way of doing it. MBS has some functions which (I think) can bring a known PID application to the front, but I want to do it within Xojo.

Thanks

I assume you’re building for Windows? If so then see this thread. It discusses how to use a mutex to detect when another instance of your app is already running, and an IPCSocket to communicate between the first instance and subsequent instances of your app.

Thanks Andrew for the reply.

Yes, I am using Win10.

Re Mutex: Yes, I had seen that thread.
As mentioned in the question, I have no trouble detecting an existing instance of the program
(I use shell to run Tasklist and search for the application. This finds if it’s running, and also gives its PID if it is.)
I also don’t need to communicate between applications so don’t need IPCSocket.

I simply want to quit the second instance, after bringing the first instance (which is minimized with known PID) to the front.

Gary

Bringing the first instance to the front could be done by sending a message over the IPCSocket (“hey! wake up!”) and putting the actual window-frontmost-making code directly in first instance. It’s usually easier to manipulate a window from within the instance that actually owns it.

Manipulating another instance’s window will usually involve using win32 declares like FindWindowExW and BringWindowToTop.

That is a handle to the process, not the window. You simply use EnumWindows() and GetWindowThreadProcessId() to enumerate all top-level windows looking for the one(s) that belong to the Process ID you have. Then use SetForegroundWindow() to bring that window to the front making sure you comply with all the restrictions of SetForegroundWindow().

This seems to get asked about every six months. Here’s how I handle it. Remember, anything in <…> needs to be replaced with your app’s info.

' We need to know the exact name of the main window if we want to bring the first instance to the front.
' So we set it here and retrieve it for the window in its Open event
MainWindowTitle = <whatever you name your application's main or starting window>

// Look to see if the app is already executing
Dim s As shell = New Shell
s.Execute ("tasklist /fo CSV")
Dim theString As String = s.Result
Dim theStringArray () As String
theStringArray = theString.Split (<your App's Name>)
If theStringArray.LastIndex > 1 Then // There's more than one instance in the list of processes that are running
  Soft Declare Function FindWindowA Lib "User32" (className As Integer, title As CString) As Integer
  Soft Declare Function FindWindowW Lib "User32" (className As Integer, title As WString) As Integer
  
  // Find the window via an exact match using FindWindow
  Dim handle As Integer
  If System.IsFunctionAvailable ("FindWindowW", "User32") Then
    handle = FindWindowW (0, MainWindowTitle)
  Else
    handle = FindWindowA (0, MainWindowTitle)
  End If
  
  // If we found a handle, then we want to bring it to the front
  If handle <> 0 Then
    Var i As Integer
    Declare Function ShowWindow Lib "User32" (hWnd As Integer, nCmdShow As Integer) As Integer
    Declare Function BringWindowToTop Lib "User32" (hWnd As Integer) As Integer
    Declare Sub SetForegroundWindow Lib "User32" (hwnd As Integer)
    i = ShowWindow (handle, 1)
    i = BringWindowToTop (handle)
    SetForegroundWindow (handle)
   // and lastly we kill ourself and let the original one run.
    Quit
  End If
  
End If

This doesn’t send any information between the instances of the app. It merely finds and brings the first one to the front and lets the second instance go away.

2 Likes

Thanks Dale.
This is exactly what I wanted.

Thanks also for specific code example.

This seems to get asked about every six months.

Yes, that’s true - I found many references to bringing a task to the foreground.
But other replies in other threads either didn’t do what I wanted, or were incomprehensible (at least to me).

Gary

Quit the second instance after bringing all windows of the first instance to the front:

  1. Declare mMutex in the App’s Properties.

  2. In the Open event of the application:

mMutex = New Mutex(App.ExecutableFile.Name)
If Not mMutex.TryEnter Then
  dim w as new WindowsListMBS   //to list all windows on a Windows system
  dim i,c as integer
  c=w.WindowCount-1
    for i = 0 to c
      if w.WindowImageFileName(i).IndexOf(App.ExecutableFile.Name)>-1 AND w.WindowText(i).Length>0 AND w.WindowClassName(i)="RBWindow" then 
        w.ActivateWindow(i)
      end if
    next
  Quit
End If
  1. In the Close event of the application:
If mMutex <> Nil Then
  mMutex.Leave
End If

He said NO MBS, this answer uses a paid 3rd software