我正在使用C#编写一个Windows窗体应用程序,我需要将其置于前台。经过一些谷歌搜索和尝试,我有了一个看起来很鬼畜的可行解决方案。
如果有一种优雅的方法,我想知道如何做到这一点。无论应用程序是最小化的,还是未最小化但在后台,我都需要它恢复并置于前台。
当前的代码看起来像这样:
WindowState = FormWindowState.Minimized;
WindowState = FormWindowState.Normal;
BringToFront();
Focus();
我正在使用C#编写一个Windows窗体应用程序,我需要将其置于前台。经过一些谷歌搜索和尝试,我有了一个看起来很鬼畜的可行解决方案。
如果有一种优雅的方法,我想知道如何做到这一点。无论应用程序是最小化的,还是未最小化但在后台,我都需要它恢复并置于前台。
当前的代码看起来像这样:
WindowState = FormWindowState.Minimized;
WindowState = FormWindowState.Normal;
BringToFront();
Focus();
你尝试过 Form.Activate 吗?
以下代码似乎可以实现你想要的效果,如果窗体被最小化了,它会将其恢复到正常大小,并激活它以设置焦点:
if (this.WindowState == FormWindowState.Minimized)
{
this.WindowState = FormWindowState.Normal;
}
this.Activate();
警告:这很烦人!但是,如果这只是您个人使用的应用程序,就像您所说的那样,也许您可以忍受它。:)
this.Activate()
。但在另一台机器上却无法运行(理论上是相同的Windows 7版本)。这个答案解决了问题。 - Daniel Möllerprivate 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。虽然这仍然是一种hackish方法,但如果Activate和Show无法正常工作,它比最小化/重新显示要好。尝试了几次后,我找到了可行的组合:
form.Show();
form.WindowState = FormWindowState.Normal;
form.Activate();
[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;
}
实际上,只需要在 Shown
事件中调用 Activate()
。
在你的 Example.Designer.cs
文件中:
this.Shown += new System.EventHandler(this.Example_Shown);
Example.cs
文件中:private void Example_Shown(object sender, EventArgs e)
{
this.Activate();
}
即使您的表单由另一个进程启动(例如:在不同线程中运行的闪屏表单),此方法仍然有效。
如前面的回答中已经提到的,一种(当然不太优雅)的方法是使用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 );
}
}
我曾经遇到过类似的问题,
form.TopMost = true;
form.Activate();
这是一个相当令人满意的解决方案。
但是不能保证窗体一定拥有焦点,因为TopMost
可能不总是有效,这取决于用户之前如何与其他进程中的窗口进行交互:
设置.TopMost = true
然后使用
ShowDialog()
Show()
和ShowDialog()
。 - bluish