简体   繁体   English

如何在C#中将进程窗口聚焦在正在运行的Web浏览器窗口上?

[英]How to focus a process window over a running webbrowser window in c#?

I have a small Windows Forms program (agent) running in the Systray. 我有一个小的Windows窗体程序(代理)在Systray中运行。 The purpose of this agent written in C# is to start other programs, focus them and putting them into the foreground. C#编写的该代理程序的目的是启动其他程序,将它们聚焦并放在前台。

This agent receives the commands to start other programs from the browser and reports the successful start back to it. 该代理从浏览器接收启动其他程序的命令,并向其报告成功启动。 This means the browser is always up and running. 这意味着浏览器始终处于运行状态。

Starting external programs from the agent is working fine, but I have much trouble to get the focus and foreground topic to work. 从代理启动外部程序工作正常,但是要使焦点和前景主题正常工作,我遇到了很多麻烦。 It seems like the browser is always in focus and the programs started from the agent are moved right behind the browser window. 似乎浏览器始终处于焦点位置,并且从代理启动的程序被直接移到浏览器窗口的后面。

I have tried the following methods from the User32.dll without success: 我从User32.dll尝试了以下方法,但未成功:

  • SetForegroundWindow(IntPtr handle)
  • SwitchToThisWindow(IntPtr hWnd, bool fAltTab)

The strange thing is that if I am running the agent in my Visual Studio the focus works perfect! 奇怪的是,如果我在Visual Studio中运行代理,则焦点工作正常!

Help is much appreciated, since I am new to windows internals. 非常感谢您的帮助,因为我是Windows内部人员的新手。

Update 1: I noticed if for instance a powershell window (could be anything arbitrary) lays over the browser window, focusing the started process window works as expected. 更新1:我注意到,例如,如果Powershell窗口(可以是任意的)放置在浏览器窗口上方,则可以集中启动的进程窗口按预期工作。

Update 2: I was able to get the right focus by calling 更新2:我能够通过致电获得正确的关注

SetWindowPos(browserProcess.MainWindowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

on the browser process window and 在浏览器进程窗口上,

SetWindowPos(process.MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);

on the started process window. 在启动的进程窗口上。 But I think this is a bad approach since the browser window may vanish behind other open windows. 但是我认为这是一种不好的方法,因为浏览器窗口可能会在其他打开的窗口之后消失。 I have also tried 我也尝试过

SetWindowPos(browserProcess.MainWindowHandle, process.MainWindowHandle, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);

to switch the Z order of the browser window and the process window, but without success. 切换浏览器窗口和处理窗口的Z顺序,但是没有成功。

Question : How I can switch the Z order of the browser process and the started process? 问题 :如何切换浏览器进程和已启动进程的Z顺序?

Seems like SendKeys.SendWait("%"); 好像是SendKeys.SendWait("%"); was the magic I needed. 是我需要的魔术。 % is the ALT key. %是ALT键。

From the documentation of LockSetForegroundWindow 来自LockSetForegroundWindow的文档

The system automatically enables calls to SetForegroundWindow if the user presses the ALT key or takes some action that causes the system itself to change the foreground window (for example, clicking a background window). 如果用户按下ALT键或执行某些操作导致系统自身更改前景窗口(例如,单击背景窗口),则系统会自动启用对SetForegroundWindow的调用。

Calling AllowSetForegroundWindow returned FALSE in the first place so I was not able to set the foreground window. 首先调用AllowSetForegroundWindow返回FALSE ,所以我无法设置前景窗口。 A call to GetLastError revealed the error code ERROR_ACCESS_DENIED . GetLastError的调用显示了错误代码ERROR_ACCESS_DENIED Calling SendKeys.SendWait("%") before User32dll.SetForegroundWindow(windowHandle) enables calls to SetForegroundWindow to be successful. User32dll.SetForegroundWindow(windowHandle) SendKeys.SendWait("%")之前调用SendKeys.SendWait("%")可以成功调用SetForegroundWindow

To put it together it looks like this: 放在一起看起来像这样:

var windowHandle = User32dll.FindWindow(null, nameOfWindow);
SendKeys.SendWait("%");
User32dll.SetForegroundWindow(windowHandle);

If the window is minimized, using User32dll.ShowWindow(windowHandle, User32dll.SW_RESTORE) is sufficient. 如果将窗口最小化,则使用User32dll.ShowWindow(windowHandle, User32dll.SW_RESTORE)就足够了。

How do you retrieve the handle for that window? 您如何检索该窗口的句柄

This works for me: 这对我有用:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);


    SetForegroundWindow((IntPtr)handle);

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM