如何将一个未受管理的应用程序窗口置于最前,并使其成为(模拟)用户输入的活动窗口

16

我假设我需要使用PInvoke,但我不确定需要哪些函数调用。

情境:将运行一个旧应用程序,我将拥有该应用程序的句柄。

我需要:

  1. 将该应用程序置于顶部(在所有其他窗口前面)
  2. 使其成为活动窗口

需要哪些Windows函数调用?

3个回答

16

如果您没有窗口的句柄,请在此之前使用以下代码:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

现在假设您已经有了应用程序窗口的句柄:

[DllImport("user32.dll", SetLastError = true)]
static extern bool SetForegroundWindow(IntPtr hWnd);

如果另一个窗口拥有键盘焦点,这将使任务栏闪烁。

如果您想强制窗口置于前台,请使用ForceForegroundWindow(示例实现)。


SetForegroundWindow 看起来已经满足了我的需求,但是当我尝试调用 ForceForegroundWindow 时出现错误(“在 DLL 'user32.dll' 中找不到名为 'ForceForegroundWindow' 的入口点。”)。 - Gerald Davis
在我的情况下,我不得不使用“BringWindowToTop”来补充。ForceForegroundWindow完美地解决了我的问题。谢谢! - Robert Jeppesen
这是你提到的ForceForegroundWindow代码吗:http://pastebin.com/zkdZvKuG? - DDA
很遗憾,我不记得原始代码是什么了,但这是有可能的。 - user703016
@ParkYoung-Bae,我该如何在C#中包含/使用WinAPI类? - andreas
就我所知,我在这里找到了ForceForegroundWindow的完整示例:https://shlomio.wordpress.com/2012/09/04/solved-setforegroundwindow-win32-api-not-always-works/,通过http://pinvoke.net/default.aspx/user32/SetForegroundWindow.html。我似乎无法在Win 10 v1903中使其正常工作,但这可能只是我正在努力推进的应用程序的问题。 - cvocvo

16

这被证明非常可靠。ShowWindowAsync函数专门为由不同线程创建的窗口设计。SW_SHOWDEFAULT确保在显示之前将窗口恢复,并激活。

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern bool ShowWindowAsync(IntPtr windowHandle, int nCmdShow);

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern bool SetForegroundWindow(IntPtr windowHandle);

然后进行调用:

ShowWindowAsync(windowHandle, SW_SHOWDEFAULT);
ShowWindowAsync(windowHandle, SW_SHOW);
SetForegroundWindow(windowHandle);

1
其他我尝试过的代码都失败了,而这段代码却像魔法一样运行良好。 - TH Todorov
这在Windows 11上也非常有效,尝试了很多不同的方法后也是如此。 - undefined

12
    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr WindowHandle);
    public const int SW_RESTORE = 9;

ShowWindowAsync方法用于显示最小化的应用程序,而SetForegroundWindow方法用于将后台应用程序置于前面。

您可以像我在我的应用程序中一样使用这些方法,在按钮单击时将Skype置于我的应用程序之前。

private void FocusSkype()
    {
        Process[] objProcesses = System.Diagnostics.Process.GetProcessesByName("skype");
        if (objProcesses.Length > 0)
        {
            IntPtr hWnd = IntPtr.Zero;
            hWnd = objProcesses[0].MainWindowHandle;
            ShowWindowAsync(new HandleRef(null,hWnd), SW_RESTORE);
             SetForegroundWindow(objProcesses[0].MainWindowHandle);
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接