Каков "правильный" способ вывести приложение 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();
на самом деле, просто позвони 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
может работать не всегда, в зависимости от того, как пользователь взаимодействовал с окнами в других процессах:
Как уже говорилось в другом ответе, один (конечно, неэлегантный) способ сделать это-использовать 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;