Каков "правильный" способ вывести приложение Windows Forms на передний план?

Я пишу приложение Windows Forms на C#. Я должен быть в состоянии вывести это на первый план. После некоторого поиска и экспериментов у меня есть рабочее решение, которое выглядит довольно хаки.

Я хотел бы знать элегантный способ сделать это, если он есть. Мне нужно приложение для восстановления и выхода на передний план, было ли оно свернуто или не свернуто, но в фоновом режиме.

текущий код выглядит так:

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

12 ответов


ты пробовал


Примечание. Ниже я скопировал самое проголосовал за ответ на связан вопрос закрыт как дубликат этого. Этот ответ-единственный чистый ответ C#, который я нашел, который решает эту проблему.

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

Он всегда выводит желаемое окно на передний план всех остальных.


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

вы можете установить .TopMost значение true, вызов DoEvents(), а затем установить .TopMost обратно в false. Это все еще хакерский, но если активация и шоу не работают, это лучше, чем минимизация/повторное отображение.


после многих проб и ошибок я добрался до этого кода. Это проверено. Метод BringToFront вызывается в вашей форме после того, как фокус был передан ей. Это заставляет его всплывать спереди.

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

после нескольких попыток я нашел рабочую комбинацию:

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

задание Form.TopMost до true заставит окно на передний план.


set .TopMost = true

и использовать

ShowDialog()

на самом деле, просто позвони Activate() внутри Shown событие.

в своем Example.Designer.cs:

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

в своем Example.cs:

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

это сработало, даже если ваша форма запускается другим процессом (например: форма заставки, работающая в другом потоке).


у меня была аналогичная проблема, к которой

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

было довольно удовлетворительным решением.

но все равно не гарантируется, что форма будет иметь фокус, потому что TopMost может работать не всегда, в зависимости от того, как пользователь взаимодействовал с окнами в других процессах:

TopMost не работает при использовании в формах, работающих последовательно в разных потоках и закрытых кодом пользователя


Как уже говорилось в другом ответе, один (конечно, неэлегантный) способ сделать это-использовать user32.dll и вызов собственных методов, это может быть допустимо, если мы используем какой-то несвязанный процесс или поток из вызывающего окна, который был установлен в главном вызывающем в качестве фонового окна (например: всегда сверху для окна, которое мы хотим сверху).

Это было частично скопировано, но только для простоты:

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

для полноты я добавил большинство ссылок из константы, доступные в Windows SDK


вместо использования windowstate minimize или topmost=false и т. д...

У меня есть Winform приложение... он запускает процедуру автоматизации - я хотел, чтобы приложение было сведено к минимуму, когда выполняется последовательность автоматизации, а затем представлено снова после завершения последовательности автоматизации.

Это было легко - просто сделайте форму не видимой, пока другой процесс/поток/ все, что работает

 //hide the app

 this.Visible=false;

 //do something 

 some_form.ShowDialog();
 doSomethingHere();

 //reshow the app

 this.visible=true;