我在Systray中运行着一个小的Windows窗体程序(代理)。用C#
编写的该代理的目的是启动其他程序,将它们聚焦并放在前台。
此代理从浏览器接收启动其他程序的命令,并向其报告成功启动。这意味着浏览器始终处于运行状态。
从代理启动外部程序可以正常工作,但是要使焦点和前景主题正常工作很困难。似乎浏览器始终处于焦点位置,并且从代理启动的程序被直接移到浏览器窗口的后面。
我从User32.dll
开始尝试了以下方法,但没有成功:
SetForegroundWindow(IntPtr handle)
SwitchToThisWindow(IntPtr hWnd, bool fAltTab)
奇怪的是,如果我在Visual Studio中运行代理,则焦点工作正常!
非常感谢您的帮助,因为我是Windows内部人员的新手。
更新1:我注意到,例如在浏览器窗口上是否放置了Powershell窗口(可以是任意对象),以使启动的进程窗口按预期工作。
更新2:我能够通过致电来获得正确的关注
SetWindowPos(browserProcess.MainWindowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
在浏览器进程窗口和
SetWindowPos(process.MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
在启动的进程窗口中。但是我认为这是一种不好的方法,因为浏览器窗口可能会在其他打开的窗口之后消失。我也尝试过
SetWindowPos(browserProcess.MainWindowHandle, process.MainWindowHandle, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
切换浏览器窗口和处理窗口的Z顺序,但没有成功。
问题:如何切换浏览器进程和已启动进程的Z顺序?
答案 0 :(得分:1)
好像SendKeys.SendWait("%");
是我需要的魔法。%
是ALT键。
摘自LockSetForegroundWindow
如果用户按下ALT键或采取了某些措施导致系统自身更改了前景窗口(例如,单击背景窗口),则系统会自动启用对SetForegroundWindow的调用。
首先致电AllowSetForegroundWindow
返回了FALSE
,所以我无法设置前台窗口。对GetLastError
的调用显示了错误代码ERROR_ACCESS_DENIED
。在SendKeys.SendWait("%")
之前调用User32dll.SetForegroundWindow(windowHandle)
可以成功调用SetForegroundWindow
。
将其放在一起看起来像这样:
var windowHandle = User32dll.FindWindow(null, nameOfWindow);
SendKeys.SendWait("%");
User32dll.SetForegroundWindow(windowHandle);
如果窗口最小化,则使用User32dll.ShowWindow(windowHandle, User32dll.SW_RESTORE)
就足够了。
答案 1 :(得分:0)
如何获取该窗口的句柄?
这对我有用:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
SetForegroundWindow((IntPtr)handle);