代码之家  ›  专栏  ›  技术社区  ›  D'Arcy Rittich

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

  •  30
  • D'Arcy Rittich  · 技术社区  · 15 年前

    我正在用C语言编写一个Windows窗体应用程序。我需要能把它带到前景。经过一些谷歌搜索和实验,我有了一个看起来很糟糕的工作解决方案。

    如果有的话,我想知道优雅的方法。我需要应用程序恢复到前台,不管它是最小化的,还是不最小化,而是在后台。

    当前代码如下:

    WindowState = FormWindowState.Minimized;
    WindowState = FormWindowState.Normal;
    BringToFront();
    Focus();
    
    12 回复  |  直到 6 年前
        1
  •  47
  •   bobbymcr    15 年前

    你试过了吗? Form.Activate ?

    此代码似乎按您的需要执行,方法是将最小化后的窗体还原为正常大小,然后激活它以设置焦点:

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

    警告:这很烦人!如果它只是一个你个人使用的应用程序,如你所说,也许你可以接受它。:)

        2
  •  10
  •   Community Reversed Engineer    7 年前

    注意事项。以下是我抄袭最多的 voted answer 在一个 linked question 作为与此相同的副本关闭。这个答案是我发现的唯一一个解决这个问题的纯C答案。

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

    它总是把所需的窗口带到所有其他窗口的前面。

        3
  •  7
  •   bluish dmajkic    6 年前
    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);
        }
    }
    
        4
  •  5
  •   Joel Coehoorn    15 年前

    你可以设定 .TopMost 真实,呼叫 DoEvents() 然后设置 最上面的 回到错误。这仍然是黑客,但如果激活和显示不起作用,它比最小化/重新显示要好。

        5
  •  2
  •   Democrats    9 年前

    经过反复的试验和错误之后,我得到了这个代码。 这是测试过的。 焦点传递到窗体之后,将在窗体上调用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;
    }
    
        6
  •  1
  •   AlexThunder    6 年前

    经过几次尝试,我发现了工作组合:

    form.Show();
    form.WindowState = FormWindowState.Normal;
    form.Activate();
    
        7
  •  0
  •   Jim Fell    8 年前

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

        8
  •  0
  •   Roman Marusyk S Kotra    8 年前

    设置 .TopMost = true

    使用

    ShowDialog()
    
        9
  •  0
  •   codenamezero    7 年前

    实际上,只要打电话 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();
    }
    

    即使您的表单正由另一个进程启动(例如:在另一个线程中运行的启动屏幕表单),这也会起作用。

        10
  •  0
  •   Philip    7 年前

    我也有类似的问题

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

    是一个非常令人满意的解决方案。

    但是它仍然不能保证形式会有焦点,因为 TopMost 可能并不总是有效,这取决于用户以前如何与其他进程中的窗口进行交互:

    TopMost does not work when used on Forms running in consecutively in different threads and closed by user code

        11
  •  0
  •   Sascha    6 年前

    如另一个响应中所述,实现此目的的一种方法(当然是unelegant)是使用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中可用常量的大多数引用

        12
  •  -1
  •   Leonardo Alves Machado Vivek Kumar    6 年前

    而不是使用windowstate minimize或topmost=false等…

    我有一个WinForm应用程序…它启动了一个自动化程序——我希望在执行自动化程序时应用程序最小化,然后在完成自动化程序后再次显示。

    这很简单——只需在其他进程/线程/任何正在运行的对象运行时使窗体不可见即可。

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