【问题标题】:Bring another processes Window to foreground when it has ShowInTaskbar = false当 ShowInTaskbar = false 时,将另一个进程窗口置于前台
【发布时间】:2011-02-07 20:48:05
【问题描述】:

我们只希望我们的应用程序在任何时候都运行一个实例。因此,在启动时,它会查看应用程序是否正在运行,如果是,它会在主窗口上调用 SetForegroundWindow

这一切都很好...... 大部分......

当我们的应用启动时,它会显示一个启动画面和一个登录表单。这两种形式都有ShowInTaskBar = false

因此,如果您在显示登录表单时尝试启动应用程序的另一个副本,则该登录表单不会被带到最前面

特别是当用户在任务栏中也看不到任何东西时,他们认为应用程序是 duff 并且无法启动。没有迹象表明正在运行另一个实例。

有没有办法解决这个问题?

【问题讨论】:

  • 问题:设置Logon表单的Owner属性是不能解决还是没有效果?

标签: c# winforms


【解决方案1】:

好吧,代码在这里。即使ShowInTaskBarfalse,你也应该可以把它带到前面。

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);

    [DllImport("USER32.DLL")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    public static void bringToFront(string title) {
        // Get a handle to the Calculator application.
        IntPtr handle = FindWindow(null, title);

        // Verify that Calculator is a running process.
        if (handle == IntPtr.Zero) {
            return;
        }

        // Make Calculator the foreground application
        SetForegroundWindow(handle);
    }

注意:您应该FindWindow 使用表单的类而不是名称,因为启动屏幕表单有时没有标题,甚至没有控制框。使用 Spy++ 深入挖掘。

在启动时使用FindWindow。我认为这就是您想要做的 - 在加载主表单时将启动画面放在前面。

【讨论】:

  • 我正在执行 System.Diagnostics.Process.GetProcessesByName 调用以获取进程,然后在 process.MainWindowHandle 上调用 SetForegroundWindow。没有 ShowInTaskbar,就没有 MainWindowHandle。 FindWindow 是解决此问题的好方法。谢谢!
  • 这么多方法可以做到这一点,但这是唯一对我有用的方法!
  • 一个请求:如果你加-ve分,请给出你的理由/观点。谢谢大家。
  • 如果计算器最小化,则无法在 Windows 10 下运行。
【解决方案2】:

我认为这是更好的解决方案,因为它可以从最小化状态恢复:

public static class WindowHelper
{
    public static void BringProcessToFront(Process process)
    {
        IntPtr handle = process.MainWindowHandle;
        if (IsIconic(handle))
        {
            ShowWindow(handle, SW_RESTORE);
        }

        SetForegroundWindow(handle);
    }

    const int SW_RESTORE = 9;

    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool SetForegroundWindow(IntPtr handle);
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
    [System.Runtime.InteropServices.DllImport("User32.dll")]
    private static extern bool IsIconic(IntPtr handle);
}

简单的调用:

WindowHelper.BringProcessToFront(process);

【讨论】:

  • 赞成这个答案,因为它也从最小化状态恢复。
  • 只是想补充一下,它在调试模式下不起作用 - 该进程将被设置为活动状态,然后再次隐藏。但如果你只是运行你的应用程序,它就可以正常工作。
  • 我赞成这个解决方案,因为它提到了如何使用进程句柄来做到这一点。此外,我喜欢答案的完整性,包括 pinvoke 的内容。
  • 这里有一个比更好的解决方案更好的解决方案:stackoverflow.com/questions/46974192/…
  • 如果计算器最小化,则无法在 Windows 10 下运行。
【解决方案3】:
FindWindow(null, title);

将找到与查询匹配的第一个窗口。如果另一个窗口使用相同的标题,这可能会导致意外行为。

尽管发生这种情况的机会似乎很少或不可能(单实例应用程序),但这种情况很容易发生。例如,Windows 资源管理器使用所选目录的名称作为窗口标题(虽然不可见)。现在,如果窗口标题是一个通用术语或与应用程序目录的名称匹配,这可能是一个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-21
    • 2012-05-04
    • 1970-01-01
    相关资源
    最近更新 更多