如何聚焦外窗?
我有一个应用程序,一次只能打开一个自己的实例。 为了强制执行此操作,我使用以下代码:
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消息,你可以将其解释为“其他一些实例想要把我带到前面”。