Qual è il modo “giusto” per portare in primo piano un’applicazione Windows Form?

Sto scrivendo un’applicazione Windows Form in C #. Devo essere in grado di portarlo in primo piano. Dopo alcune ricerche su Google e la sperimentazione, ho una soluzione funzionante che sembra piuttosto hacky.

Mi piacerebbe sapere il modo elegante per farlo, se ce n’è uno. Ho bisogno che l’app ripristini e arrivi in ​​primo piano se è stata ridotta a icona, o non ridotta a icona, ma in background.

Il codice attuale ha questo aspetto:

WindowState = FormWindowState.Minimized; WindowState = FormWindowState.Normal; BringToFront(); Focus(); 

Hai provato Form.Attiva ?

Questo codice sembra fare ciò che desideri, ripristinando il formato a dimensioni normali se ridotto a icona e quindi triggersndolo per impostare lo stato attivo:

 if (this.WindowState == FormWindowState.Minimized) { this.WindowState = FormWindowState.Normal; } this.Activate(); 

Attenzione: questo è fastidioso! Se è solo un’app per uso personale, come dici tu, forse puoi conviverci. 🙂

Nota. Di seguito ho copiato la risposta più votata in una domanda collegata chiusa come duplicata a questa. Questa risposta è l’unica risposta C # pura che ho trovato che risolva questo problema.

 this.WindowState = FormWindowState.Minimized; this.Show(); this.WindowState = FormWindowState.Normal; 

Porta sempre la finestra desiderata davanti a tutti gli altri.

 private static class User32 { [DllImport("User32.dll")] internal static extern IntPtr SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); internal static readonly IntPtr InvalidHandleValue = IntPtr.Zero; internal const int SW_MAXIMIZE = 3; } public void Activate() { Process currentProcess = Process.GetCurrentProcess(); IntPtr hWnd = currentProcess.MainWindowHandle; if (hWnd != User32.InvalidHandleValue) { User32.SetForegroundWindow(hWnd); User32.ShowWindow(hWnd, User32.SW_MAXIMIZE); } } 

È ansible impostare .TopMost su true, chiamare DoEvents() , quindi impostare .TopMost su false. È ancora un hacker, ma se Activate e Show non funzionano, è meglio che minimizzare / mostrare nuovamente.

Dopo un sacco di tentativi ed errori sono arrivato a questo codice. Questo è testato. Il metodo BringToFront viene richiamato sul modulo dopo che lo stato attivo è stato trasferito su di esso. Questo lo fa apparire davanti.

 [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr hWnd); public static bool BringToFrontCustom(Form f) { bool toReturn = true; try { //This is the same as the name of the executable without the .exe at the end Process[] processes = Process.GetProcessesByName("MyFormName"); SetForegroundWindow(processes[0].MainWindowHandle); f.BringToFront(); } catch(Exception e) { toReturn = false; MessageBox.Show("Something went wrong, Please bring the window to front manually"); } return toReturn; } 

Dopo diversi tentativi ho scoperto una combinazione di lavoro:

 form.Show(); form.WindowState = FormWindowState.Normal; form.Activate(); 

Impostando Form.TopMost su true si forzerà la finestra del form in primo piano.

set .TopMost = true

e usare

 ShowDialog() 

In realtà, basta chiamare Activate() all’interno dell’evento Shown .

Nel tuo Example.Designer.cs :

 this.Shown += new System.EventHandler(this.Example_Shown); 

Nel tuo Example.cs :

 private void Example_Shown(object sender, EventArgs e) { this.Activate(); } 

Questo ha funzionato anche se il tuo modulo è stato avviato da un altro processo (es: un modulo di splash screen in esecuzione in un thread diverso).

Ho avuto un problema simile, al quale

 form.TopMost = true; form.Activate(); 

è stata una soluzione abbastanza soddisfacente.

Ma non è ancora garantito che il modulo sarà focalizzato, perché TopMost potrebbe non funzionare sempre, a seconda di come l’utente ha interagito prima con le windows in altri processi:

TopMost non funziona se utilizzato su Form in esecuzione in modo consecutivo in thread diversi e chiuso dal codice utente

Come già affermato in un’altra risposta, un modo (ovviamente poco elegante) per farlo sarebbe utilizzare user32.dll e chiamare i metodi nativi, questo può essere valido se stiamo usando un processo non collegato o un thread dal chiamante della finestra, che era impostato nel chiamante principale come finestra di sfondo (es .: sempre in primo piano per la finestra che vogliamo in alto).

questo è stato parzialmente copiato, ma solo per facilità:

 public enum WindowPos : int { HWND_NOTOPMOST=-2, HWND_TOPMOST=-1, HWND_TOP=0, HWND_BOTTOM=1 } public enum WindowFlags : uint { SWP_NOSIZE=0x0001, SWP_NOMOVE=0x0002, SWP_NOZORDER=0x0004, SWP_NOREDRAW=0x0008, SWP_NOACTIVATE=0x0010, SWP_FRAMECHANGED=0x0020, /* The frame changed: send WM_NCCALCSIZE */ SWP_SHOWWINDOW=0x0040, SWP_HIDEWINDOW=0x0080, SWP_NOCOPYBITS=0x0100, SWP_NOOWNERZORDER=0x0200, /* Don't do owner Z ordering */ SWP_NOSENDCHANGING=0x0400 /* Don't send WM_WINDOWPOSCHANGING */ } public enum ShowWindowCommands : int { SW_HIDE=0, SW_SHOWNORMAL=1, SW_NORMAL=1, SW_SHOWMINIMIZED=2, SW_SHOWMAXIMIZED=3, SW_MAXIMIZE=3, SW_SHOWNOACTIVATE=4, SW_SHOW=5, SW_MINIMIZE=6, SW_SHOWMINNOACTIVE=7, SW_SHOWNA=8, SW_RESTORE=9, SW_SHOWDEFAULT=10, SW_FORCEMINIMIZE=11, SW_MAX=11 } private static class User32 { [DllImport("user32.dll")] internal static unsafe extern IntPtr SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] internal static unsafe extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] internal static unsafe extern bool SetWindowPos(IntPtr hWnd, int hWndPutAfter, int x, int y, int cx, int cy, uint flags); [DllImport("user32.dll")] internal static unsafe extern IntPtr SetFocus( IntPtr hWnd ); } public void Activate() { Process currentProcess = Process.GetCurrentProcess(); IntPtr hWnd = currentProcess.MainWindowHandle; if (hWnd != IntPtr.Zero) { User32.SetWindowPos(hWnd, (int)WindowPos.Top, 0, 0, 0, 0, (uint)(WindowFlags.SWP_NOMOVE | WindowFlags.SWP_NOSIZE)); User32.ShowWindow(hWnd, (int)ShowWindowCommands.SW_SHOW); User32.SetForegroundWindow(hWnd); User32.SetFocus( hWnd ); } } 

Per completezza ho aggiunto la maggior parte dei riferimenti dalle costanti disponibili in Windows SDK

Invece di usare windowstate minimizzare o topmost = false etc etc …

Ho una Winform App … avvia una routine di automazione – Volevo che l’app fosse ridotta al minimo quando viene eseguita la sequenza di automazione, quindi presentata nuovamente dopo il completamento della sequenza di automazione.

È stato facile: basta rendere il modulo non visibile mentre l’altro processo / thread / qualsiasi cosa è in esecuzione

  //hide the app this.Visible=false; //do something some_form.ShowDialog(); doSomethingHere(); //reshow the app this.visible=true;