如何聚焦外窗?

我有一个应用程序,一次只能打开一个自己的实例。 为了强制执行此操作,我使用以下代码:

System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses(); System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess(); foreach (System.Diagnostics.Process p in myProcesses) { if (p.ProcessName == me.ProcessName) if (p.Id != me.Id) { //if already running, abort this copy. return; } } //launch the application. //... 

它工作正常。 我还希望它能够集中已经运行的副本的forms。 也就是说,在返回之前,我想将此应用程序的其他实例置于前台。

我怎么做?

Re:SetForeGroundWindow:

SetForeGroundWindow工作到一定程度:

  [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); //... if (p.Id != me.Id) { //if already running, focus it, and then abort this copy. SetForegroundWindow(p.MainWindowHandle); return; } //... 

如果窗口没有最小化,这会将窗口带到前台。 真棒。 但是,如果窗口IS最小化,它将保持最小化。

它需要取消最小化。

通过SwitchToThisWindow解决方案(Works!):

  [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); [STAThread] static void Main() { System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess(); System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcessesByName(me.ProcessName); foreach (System.Diagnostics.Process p in myProcesses) { if (p.Id != me.Id) { SwitchToThisWindow(p.MainWindowHandle, true); return; } } //now go ahead and start our application ;-) 

我有同样的问题, SwitchToThisWindow()对我来说效果最好。 唯一的限制是您必须安装XP sp1。 我玩SetForegroundWindow,ShowWindow,他们都有问题拉窗口进入视图。

与OP相同,我发现当窗口最小化时,单独的SetForegroundWindow是不够的。 由于我不想使用SwitchToThisWindow ,我选择ShowWindow然后选择SetForegroundWindow

对我有用!

 private const SW_SHOWNORMAL = 1  _ Private Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As integer) As Boolean End Function  _ Private Function SetForegroundWindow(ByVal hwnd As IntPtr) As Boolean End Function Sub SetForeground() Dim processes As Process() = Process.GetProcessesByName("myprocess") For Each p as Process in processes ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL) SetForegroundWindow(p.MainWindowHandle) Next End Sub 

我相信你会想要使用SetForegroundWindow

MSDN示例

完整的旁注……

您可以使用

 Process.GetProcessesByName(me.ProcessName) 

而不是循环遍历系统上运行的所有进程……

UPDATE

针对此类事情的PInvoke规则……

C#相当于Tom Juergens的答案。 对我来说就像一个魅力。

  private const int SW_SHOWNORMAL = 1; [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow); [DllImport("user32.dll", SetLastError = true)] private static extern bool SetForegroundWindow(IntPtr hwnd); public void SetForeground() { Process[] processes = Process.GetProcessesByName("process name"); foreach (Process p in processes) { ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL); SetForegroundWindow(p.MainWindowHandle); } } 

你可以获取Process对象的MainWindowHandle属性并向它发送一条WM_USER消息,你可以将其解释为“其他一些实例想要把我带到前面”。