Qual é a maneira “certa” de colocar um aplicativo do Windows Forms em primeiro plano?

Eu estou escrevendo um aplicativo Windows Forms em c #. Eu preciso ser capaz de trazê-lo para o primeiro plano. Depois de algumas pesquisas e pesquisas, eu tenho uma solução funcional que parece bastante hacky.

Eu gostaria de saber a maneira elegante de fazer isso, se houver um. Eu preciso que o aplicativo restaure e chegue em primeiro plano se foi minimizado ou não minimizado, mas em segundo plano.

O código atual se parece com isto:

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

Você já tentou Form.Activate ?

Este código parece fazer o que você deseja, restaurando o formulário para o tamanho normal se minimizado e, em seguida, ativando-o para definir o foco:

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

Atenção: isso é chato! Se é apenas um aplicativo para seu uso pessoal, como você diz, talvez você possa viver com ele. 🙂

Nota. Abaixo, copiei a resposta mais votada em uma pergunta vinculada fechada como duplicada para esta. Essa resposta é a única resposta C # pura que encontrei que resolve esse problema.

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

Ele sempre traz a janela desejada para a frente de todos os outros.

 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); } } 

Você pode definir .TopMost como true, chamar DoEvents() e, em seguida, definir .TopMost como false. Ainda é hackish, mas se Activate and Show não estiver funcionando, é melhor que minimizar / re-mostrar.

Depois de muita tentativa e erro, cheguei a esse código. Isso é testado. O método BringToFront é chamado em seu formulário depois que o foco foi passado para ele. Isso faz aparecer na frente.

 [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; } 

Depois de várias tentativas, descobri uma combinação de trabalho:

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

Definir Form.TopMost como true forçará a janela de formulário para o primeiro plano.

definir .TopMost = true

E use

 ShowDialog() 

Na verdade, basta chamar Activate() dentro do evento Shown .

Em seu Example.Designer.cs :

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

No seu Example.cs :

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

Isso funcionou mesmo se seu formulário estivesse sendo iniciado por outro processo (ex: um formulário de canvas inicial executando em um thread diferente).

Eu tive um problema semelhante, ao qual

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

foi uma solução bastante satisfatória.

Mas ainda não é garantido que o formulário terá foco, pois o TopMost nem sempre funciona, dependendo de como o usuário interagiu antes com as janelas em outros processos:

TopMost não funciona quando usado em formulários em execução consecutivamente em segmentos diferentes e fechado pelo código do usuário

Como já foi dito em outra resposta, uma maneira (obviamente deselegante) de fazer isso seria usando user32.dll e chamar os methods nativos, isso pode ser válido se estivermos usando algum processo desvinculado ou thread do chamador da janela, que foi definido no chamador principal como uma janela de fundo (por exemplo: sempre no topo para a janela que queremos mais alto).

isso foi parcialmente copiado, mas apenas para facilidade:

 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 ); } } 

Para completar, adicionei a maioria das referências das constantes que estão disponíveis no SDK do Windows

Em vez de usar windowstate minimize ou topmost = false etc etc …

Eu tenho um aplicativo Winform … ele inicia uma rotina de automação – eu queria que o aplicativo fosse minimizado quando a seqüência de automação fosse executada e apresentada novamente após a conclusão da sequência de automação.

Foi fácil – basta tornar o formulário não visível enquanto o outro processo / thread / o que está sendo executado

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