简体   繁体   English

将Windows窗体应用程序带到前台的“正确”方法是什么?

[英]What is the “right” way to bring a Windows Forms Application to the foreground?

I am writing a Windows Forms Application in C#. 我正在用C#编写Windows窗体应用程序。 I need to be able to bring it to the foreground. 我需要能够把它带到前台。 After some Googling and experimentation, I have a working solution that looks pretty hacky. 经过一些谷歌搜索和实验,我有一个看起来非常h​​acky的工作解决方案。

I would like to know the elegant way to do this, if there is one. 如果有的话,我想知道这样做的优雅方式。 I need the app to restore and come to the foreground whether it was minimized, or not minimized but in background. 我需要应用程序恢复并前往前台,无论它是最小化,还是最小化,但在后台。

Current code looks like this: 当前代码如下所示:

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

Have you tried Form.Activate ? 你试过Form.Activate吗?

This code seems to do what you want, by restoring the form to normal size if minimized and then activating it to set the focus: 此代码似乎可以执行您想要的操作,如果最小化则将表单恢复为正常大小,然后激活它以设置焦点:

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

this.Activate();

Warning: this is annoying! 警告:这很烦人! If it's just an app for your personal use, as you say, maybe you can live with it. 如果它只是一个供您个人使用的应用程序,正如您所说,也许您可​​以忍受它。 :) :)

Note. 注意。 Below I have copied the most voted answer in a linked question closed as a duplicate to this one. 下面我复制了一个链接问题中 投票最多的答案 ,该问题与此问题相同。 That answer is the only pure C# answer I've found that solves this problem. 答案是我发现解决这个问题的唯一纯粹的C#答案。

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

It always brings the desired window to the front of all the others. 它总是将所需的窗口带到所有其他窗口的前面。

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

You can set .TopMost to true, call DoEvents() , and then set .TopMost back to false. 您可以将.TopMost设置为true,调用DoEvents() ,然后将.TopMost设置为false。 It's still hackish, but if Activate and Show aren't working it's better than minimizing/re-showing. 它仍然是hackish,但如果Activate和Show不起作用,它比最小化/重新显示更好。

After a lot of trial and error I got to this code. 经过大量的反复试验后,我得到了这段代码。 This is tested. 这是经过测试的。 The BringToFront method is called on your form after the focus has been passed on to it. 在将焦点传递给表单后,将在表单上调用BringToFront方法。 This makes it pop up in front. 这使它弹出前面。

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

After several attempts I found out working combination: 经过几次尝试,我发现了工作组合:

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

Form.TopMost设置为true将强制窗体窗口到前台。

set .TopMost = true set .TopMost = true

and use 并使用

ShowDialog()

Actually, just call Activate() inside Shown event. 实际上,只需在Shown事件中调用Activate()

In your Example.Designer.cs : Example.Designer.cs

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

In your Example.cs : 在您的Example.cs

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

This worked even if your form is being launch by another process (ex: a splash screen form running in a different thread). 即使您的表单由另一个进程启动(例如:在不同线程中运行的启动屏幕表单),这也有效。

I had a similar problem, to which 我遇到了类似的问题

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

was quite a satisfying solution. 是一个非常令人满意的解决方案

But it's still not guaranteed that the form will have focus then, because TopMost might not always work, depending on how the user has interacted before with the windows in other processes: 但是仍然不能保证表单会有焦点,因为TopMost可能并不总是有效,这取决于用户之前与其他进程中的窗口进行交互的方式:

TopMost does not work when used on Forms running in consecutively in different threads and closed by user code 当在连续运行在不同线程中并由用户代码关闭的表单上使用时,TopMost不起作用

As already stated in another response, one (of course unelegant) way to do this would be by using user32.dll and call the native methods, this can be valid if we are using some unlinked process or thread from the window caller, that was set in the main caller as a background window (eg: always on top for the window that we want topmost). 正如在另一个响应中已经说明的那样,一个(当然是不优雅的)方法是使用user32.dll并调用本机方法,如果我们使用来自窗口调用者的一些未链接的进程或线程,这可能是有效的,在主调用者中设置为背景窗口(例如:总是在我们想要最顶层的窗口的顶部)。

this was partially copied, but only for easyness: 这是部分复制,但只是为了方便:

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

For completeness I added most references from the constants that are available in the windows SDK 为了完整性,我添加了Windows SDK中可用常量的大多数引用

Instead of using windowstate minimize or topmost=false etc etc... 而不是使用windowstate最小化或topmost = false等等...

I have a Winform App... it launches an automation routine - I wanted the app minimized when the automation sequence is performed then presented again after the automation sequence was complete. 我有一个Winform应用程序......它启动了一个自动化程序 - 我希望在执行自动化程序时最小化应用程序,然后在自动化程序完成后再次显示。

It was easy - just make the form not visible while the other process/thread/ whatever is running 这很简单 - 只需使表单不可见,而另一个进程/线程/正在运行

 //hide the app

 this.Visible=false;

 //do something 

 some_form.ShowDialog();
 doSomethingHere();

 //reshow the app

 this.visible=true;  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Windows窗体:允许重叠控件的正确方法是什么? - Windows Forms: What's the right way to allow overlapping Controls? .NET Windows窗体应用程序更新自身的最佳方法是什么? - What's the best way for a .NET windows forms application to update itself? 将 window 带到前台拒绝在 windows 中工作 10 - Bring window to foreground refuses to work in windows 10 C#控制台应用程序将进程带到前台 - C# console application bring process to foreground 有什么方法可以将 Unity3d 带到前台? - Any way to bring Unity3d to the foreground? 验证.NET Windows窗体的正确方法是什么? - What is the right method of validating .NET Windows Forms? Windows中是否有一种方法可以为具有DPI感知功能的前台应用程序获取正确的矩形? - Is there a way in Windows that can get the correct rectangle for the foreground application with DPI awareness? 如何将“所有表单”带到前台(WindowsMo​​bile / C#) - How to bring “all forms” to foreground (WindowsMobile/C#) 有没有办法加密Windows窗体应用程序的配置文件? - Is there a way to encrypt the configuration file of a Windows Forms application? 有没有办法知道C#Windows Forms应用程序启动期间发生了什么 - Is there any way to know what happening during C# Windows Forms application start
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM