2010-04-14 16 views
31

Vogliamo una sola istanza della nostra applicazione in esecuzione in qualsiasi momento. Quindi all'avvio sembra vedere se l'app è in esecuzione e, in caso affermativo, chiama SetForegroundWindow nella finestra principale.Portare un'altra processi Finestra di primo piano quando ha ShowInTaskbar = false

Questo è tutto buono e ben ... per la maggior parte ..

Quando la nostra applicazione si avvia mostrerà una schermata iniziale e di un modulo di accesso. Entrambe queste forme hanno ShowInTaskBar = false.

Per questo motivo, se si tenta di avviare un'altra copia dell'app quando viene visualizzato il modulo di accesso, il modulo di accesso non viene portato in primo piano!

Tanto più che l'utente cant vedere nulla nella barra delle applicazioni, così, tutti hanno dato è che l'applicazione è duff e non può iniziare. Non c'è indicazione che ci sia un'altra istanza in esecuzione.

C'è qualche modo per aggirare questo problema?

+0

Domanda: impostando la proprietà proprietario del modulo di accesso non risolvono questo o fa non ha alcun effetto? – Asher

risposta

41

Bene, il codice è qui. Anche se ShowInTaskBar è false, dovresti riuscire a portarlo in primo piano.

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)] 
    public static extern IntPtr FindWindow(String lpClassName, String lpWindowName); 

    [DllImport("USER32.DLL")] 
    public static extern bool SetForegroundWindow(IntPtr hWnd); 

    public static void bringToFront(string title) { 
     // Get a handle to the Calculator application. 
     IntPtr handle = FindWindow(null, title); 

     // Verify that Calculator is a running process. 
     if (handle == IntPtr.Zero) { 
      return; 
     } 

     // Make Calculator the foreground application 
     SetForegroundWindow(handle); 
    } 

Nota: si dovrebbe FindWindow utilizzando la classe del form e non in base al nome, come le forme splash screen a volte non hanno titoli o anche il ControlBox. Usa Spy ++ per scavare più a fondo.

Usa FindWindow su spruzzata. Penso che questo sia quello che vuoi fare: porta lo splash screen davanti mentre carichi il modulo principale.

+0

Stavo eseguendo una chiamata System.Diagnostics.Process.GetProcessesByName per ottenere il processo e quindi chiamare SetForegroundWindow sul processo. MainWindowHandle. Senza ShowInTaskbar, non esisteva MainWindowHandle. FindWindow è un buon modo per aggirare questo problema. Grazie! –

+0

Tanti modi per farlo ancora questo è stato l'unico che ha funzionato per me! – Lee

0
FindWindow(null, title); 

Troverà la prima finestra che corrisponde alla query. Ciò potrebbe comportare un comportamento imprevisto se un'altra finestra utilizza lo stesso titolo.

Anche se si possono verificare facilmente le probabilità che ciò accada può sembrare (applicazione singola istanza) raro o impossibile questo. Windows Explorer, ad esempio, usa il nome della directory selezionata come titolo della finestra (anche se invisibile). Ora se il titolo della finestra è un termine comune o corrisponde al nome della directory dell'applicazione, questo può essere un problema.

16

Penso che questa sia la soluzione migliore, perché i suoi ripristini da stato ridotto a icona:

public static class WindowHelper 
{ 
    public static void BringProcessToFront(Process process) 
    { 
     IntPtr handle = process.MainWindowHandle; 
     if (IsIconic(handle)) 
     { 
      ShowWindow(handle, SW_RESTORE); 
     } 

     SetForegroundWindow(handle); 
    } 

    const int SW_RESTORE = 9; 

    [System.Runtime.InteropServices.DllImport("User32.dll")] 
    private static extern bool SetForegroundWindow(IntPtr handle); 
    [System.Runtime.InteropServices.DllImport("User32.dll")] 
    private static extern bool ShowWindow(IntPtr handle, int nCmdShow); 
    [System.Runtime.InteropServices.DllImport("User32.dll")] 
    private static extern bool IsIconic(IntPtr handle); 
} 

semplice chiamata:

WindowHelper.BringProcessToFront(process); 
+1

Upvoting di questa risposta poiché ripristina anche da uno stato ridotto al minimo. – oppassum

Problemi correlati