我们公司有一个作为任务栏图标运行的应用程序,除了任务栏图标之外没有任何UI。
某些事件会导致任务栏启动explorer.exe以显示目录。用户交互不会导致这种情况,因此我们的应用程序没有焦点。
我能够在windows资源管理器中使用如下代码显示目录:
Process.Start("explorer.exe", "c:somedirectory");
问题是,文件夹在后台启动,我似乎无法集中注意力。
部分问题是explorer.exe进程立即退出,单独启动explorer..exe进程。我可以使用Process.processes()
找到启动的窗口,并查看窗口标题和进程的开始时间。
一旦我终于掌握了这个过程(并等待它打开),我就会努力集中注意力
//trying to bring the application to the front
form.TopMost = true;
form.Activate();
form.BringToFront();
form.Focus();
Process process = ...;
ShowWindow(process.Handle, WindowShowStyle.ShowNormal);
SetForegroundWindow(process.Handle);
SwitchToThisWindow(process.Handle, true);
ShowWindow(process.MainWindowHandle, WindowShowStyle.ShowNormal);
SetForegroundWindow(process.MainWindowHandle);
SwitchToThisWindow(process.MainWindowHandle, true);
这会使任务栏中的窗口闪烁,但它仍然没有聚焦。
我怎样才能把窗户移到屏幕的前面?
您可以使用Shell.Application
脚本接口要求Explorer创建并显示一个新窗口。我相信使用类型化接口也是可能的,但我现在无法理解确切的接口。
var shellApplication = Type.GetTypeFromProgID("Shell.Application");
dynamic shell = Activator.CreateInstance(shellApplication);
shell.Open(@"C:drop");
这似乎打开了有焦点的窗口(在Win 8.1上使用计时器进行测试,计时器在30秒后打开,然后在有焦点的web浏览器中导航,直到计时器启动)。
要聚焦explorer.exe
,应用程序本身需要聚焦。WinForms故意使其变得困难,因为它可能被滥用。
以下是如何在WinForms中窃取焦点。请记住,这可能会产生不良后果。
一旦你的应用程序有了焦点,你就可以关注另一个过程:
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
SetForegroundWindow(otherProcess.MainWindowHandle);
以下是我如何找到explorer过程的。就像我说的,explorer.exe似乎启动了另一个进程并关闭,所以最好的选择似乎是找到最近启动的explorer..exe进程:
public static Process GetExplorerProcess()
{
var all = Process.GetProcessesByName("explorer");
Process process = null;
foreach (var p in all)
if (process == null || p.StartTime > process.StartTime)
process = p;
return process;
}
另一个不需要转移焦点的选项是显示托盘图标中的消息。然后,您可以设置一个点击处理程序来打开/聚焦文件夹。应用程序自然会从点击中获得焦点。
trayIcon.ShowBalloonTip(3000, "", msg, ToolTipIcon.Info);
这更符合"不要惹恼用户",但在我的情况下,用户对必须点击气泡更为恼火。
更新
查找资源管理器进程需要应用程序的管理员权限。我发现,如果你先关注自己的应用程序,然后启动文件夹,那么文件夹就会自动聚焦。换句话说,不需要搜索当前进程并调用SetForegroundWindow
。