恢复另一个应用程序的最小化窗口

我正在向一个应用程序添加一些代码,如果它还没有运行,它将启动另一个应用程序,或者如果是,请将它带到前面。 这需要少量的interop / WinAPI代码,我已经从其他网站获得了示例,但似乎无法在Win7中工作。

如果窗口处于某种可见状态,则API的SetForegroundWindow方法就像处理一样(这将是主要情况,根据公司策略,如果外部应用程序正在运行它不应该被最小化)。 但是,如果它被最小化(exception但很重要,因为我的应用程序在这种情况下似乎什么也不做),这个方法和ShowWindow / ShowWindowAsync实际上都不会从任务栏中恢复窗口; 所有方法都只是突出显示任务栏按钮。

这是代码; 大多数工作都很好,但是对ShowWindow()的调用(我也尝试过ShowWindowAsync),无论我发送的命令是什么,都不会做我想要的事情:

[DllImport("user32.dll")] private static extern int SetForegroundWindow(IntPtr hWnd); private const int SW_SHOWNORMAL = 1; private const int SW_SHOWMAXIMIZED = 3; private const int SW_RESTORE = 9; [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); ... //The app is named uniquely enough that it can't be anything else, //and is not normally launched except by this one. //so this should normally return zero or one instance var processes = Process.GetProcessesByName("ExternalApp.exe"); if (processes.Any()) //a copy is already running { //I can't currently tell the window's state, //so I both restore and activate it var handle = processes.First().MainWindowHandle; ShowWindow(handle, SW_RESTORE); //GRR!!! SetForegroundWindow(handle); return true; } try { //If a copy is not running, start one. Process.Start(@"C:\Program Files (x86)\ExternalApp\ExternalApp.exe"); return true; } catch (Exception) { //fallback for 32-bit OSes Process.Start(@"C:\Program Files\ExternalApp\ExternalApp.exe"); return true; } 

我已经尝试过SHOWNORMAL(1),SHOWMAXIMIZED(3),RESTORE(9)以及其他几个大小调整命令,但似乎没有什么可以做到的。 思考?

编辑:我发现一些我认为正在工作的其他代码的问题。 对GetProcessesByName()的调用没有找到进程,因为我在寻找可执行文件名,而不是进程名。 这导致我认为正在运行的代码并且实际上根本没有执行。 我认为它有效,因为外部应用程序显然也会检测到副本已经在运行并尝试激活该当前实例。 我从我搜索的进程名称中删除了“.exe”,现在代码执行了; 然而,这似乎是一个倒退,因为现在当我调用ShowWindow [Async]时,任务栏按钮甚至没有突出显示。 所以,我现在知道我的应用程序和我正在调用的外部应用程序都不能在Win7中以编程方式更改不同实例的窗口状态。 什么在这里?

使用FindWindow方法的工作代码:

 [DllImport("user32.dll")] public static extern IntPtr FindWindow(string className, string windowTitle); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags); [DllImport("user32.dll")] private static extern int SetForegroundWindow(IntPtr hwnd); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetWindowPlacement(IntPtr hWnd, ref Windowplacement lpwndpl); private enum ShowWindowEnum { Hide = 0, ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3, Maximize = 3, ShowNormalNoActivate = 4, Show = 5, Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8, Restore = 9, ShowDefault = 10, ForceMinimized = 11 }; private struct Windowplacement { public int length; public int flags; public int showCmd; public System.Drawing.Point ptMinPosition; public System.Drawing.Point ptMaxPosition; public System.Drawing.Rectangle rcNormalPosition; } private void BringWindowToFront() { IntPtr wdwIntPtr = FindWindow(null, "Put_your_window_title_here"); //get the hWnd of the process Windowplacement placement = new Windowplacement(); GetWindowPlacement(wdwIntPtr, ref placement); // Check if window is minimized if (placement.showCmd == 2) { //the window is hidden so we restore it ShowWindow(wdwIntPtr, ShowWindowEnum.Restore); } //set user's focus to the window SetForegroundWindow(wdwIntPtr); } 

您可以通过调用BringWindowToFront()来使用它。

我总是有一个应用程序运行实例,所以如果你可以同时拥有几个打开的实例,你可能想稍微改变一下逻辑。

……显然你不能相信一个过程给你的信息。

Process.MainWindowHandle返回应用程序创建的第一个窗口的窗口句柄,该窗口通常是应用程序的主顶级窗口。 但是,在我的情况下,对FindWindow()的调用显示我想要恢复的实际窗口的句柄不是MainWindowHandle指向的。 在这种情况下,Process的窗口句柄似乎是程序加载主窗体时显示的初始屏幕。

如果我在FindWindow返回的句柄上调用ShowWindow,它可以完美地运行。

更不寻常的是,当窗口打开时,调用SetForegroundWindow(),当给定进程的MainWindowHandle(在该窗口关闭时应该无效)时,可以正常工作。 显然,句柄有一定的有效性,只是在窗口最小化时才有效。

总而言之,如果您发现自己陷入了困境,请调用FindWindow,将其传递给外部应用程序主窗口的已知名称,以获得所需的句柄。

我有同样的问题。 我找到的最佳解决方案是使用标志SW_MINIMIZE调用ShowWindow ,然后使用SW_RESTORE 。 :d

另一种可能的方案

 // Code to display a window regardless of its current state ShowWindow(hWnd, SW_SHOW); // Make the window visible if it was hidden ShowWindow(hWnd, SW_RESTORE); // Next, restore it if it was minimized SetForegroundWindow(hWnd); // Finally, activate the window 

来自的评论: http : //msdn.microsoft.com/en-us/library/ms633548%28VS.85%29.aspx

托盘调用ShowWindow(handle,SW_RESTORE); 在SetForegroundWindow(句柄)之后;

这可能会解决您的问题。