C# 如何对焦外部窗口?

C# 如何对焦外部窗口?,c#,.net,focus,C#,.net,Focus,我有一个应用程序,它一次只能打开一个实例。为了实现这一点,我使用以下代码: System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses(); System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess(); foreach (System.Diagno

我有一个应用程序,它一次只能打开一个实例。为了实现这一点,我使用以下代码:

        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.
        //...
它很好用。我还希望它能够集中已经运行的副本的形式。也就是说,在返回之前,我想把这个应用程序的另一个实例放到前台

我该怎么做

回复: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;
                }
    //...
如果窗口没有最小化,它会将窗口带到前台。令人惊叹的。 但是,如果窗口最小化,它将保持最小化状态

它需要取消最小化

通过切换到此窗口的解决方案(有效!):


我相信你会想用


您能抓取Process对象的MainWindowHandle属性并向其发送一条WM\u用户消息,您可以将其解释为“其他实例想让我站到前面来”

完成旁注

你可以用

Process.GetProcessesByName(me.ProcessName) 
而不是在系统上运行的所有进程上循环

更新


这类事情的规则…

我也有同样的问题,而且对我来说效果最好。唯一的限制是必须安装XP sp1。我玩过SetForeGroundIndow和ShowWindow,它们在将窗口拉入视图时都有问题。

与OP一样,我发现在最小化窗口时,仅使用
SetForeGroundIndow
是不够的。因为我不想使用
切换到此窗口
,所以我选择了
ShowWindow
,然后选择
setforegroundindow

很适合我

private const SW_SHOWNORMAL = 1

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As integer) As Boolean
End Function

<DllImport("user32.dll", SetLastError:=True)> _
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
private const SW\u SHOWNORMAL=1
_
私有函数ShowWindow(ByVal hwnd作为IntPtr,ByVal nCmdShow作为整数)作为布尔值
端函数
_
私有函数SetForegroundWindow(ByVal hwnd作为IntPtr)作为布尔值
端函数
子集合前景()
Dim processs As Process()=Process.getProcessByName(“myprocess”)
对于流程中的每个p as流程
ShowWindow(p.MainWindowHandle,SW_SHOWNORMAL)
SetForegroundWindow(p.MainWindowHandle)
下一个
端接头
C#相当于汤姆·尤尔根斯的答案。对我来说很有魅力

    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);
        }
    }

这是桌面应用程序中非常常见的行为,我在创建新的WPF应用程序时经常必须这样做。因此,我创建了一个SingletonApp类,该类继承自应用程序:

public class SingletonApp : Application
{
    private static readonly System.Threading.Mutex mutex;
    private static readonly string processName;

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int flags);

    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hwnd);

    static SingletonApp()
    {
        processName = Process.GetCurrentProcess().ProcessName;
        mutex = new System.Threading.Mutex(false, $"Local\\{processName}");
    }

    /// <summary>
    /// A base class for application needing to prevent multiple instances
    /// </summary>
    public SingletonApp()
    {
        if (!mutex.WaitOne(0, false))
        {
            // Give focus to existing instance before shutdown
            BringToFront(processName);

            Current.Shutdown();
        }
    }

    public void BringToFront(string processName)
    {
        Process process = Process.GetProcessesByName(processName).FirstOrDefault();

        if (process != null)
        {
            // In case of window is minimized
            ShowWindow(process.MainWindowHandle, 1);     // 1 = Normal

            SetForegroundWindow(process.MainWindowHandle);
        }
    }
}
不要忘了更新App.xaml:

<utils:SingletonApp x:Class="MyApp.App"
             [...]
             xmlns:utils="clr-namespace:MyApp.Utils"
             Startup="App_OnStartup">


有了它,在每一个新的桌面客户端上实现这种行为变得非常容易。

可以做到这一点,但看起来很难看。如果SetForegroundWindow无法运行,这可能是一个很好的选择。检查窗口是否为圆锥形,如果是,请调用ShowWindow。但是请注意,链接的MSDN页面上会显示“[此功能不适用于一般用途。它可能会被更改或在后续版本的Windows中不可用。]”我们如何简化上述步骤,以便快速启动已经运行的应用程序?
public partial class App : SingletonApp
<utils:SingletonApp x:Class="MyApp.App"
             [...]
             xmlns:utils="clr-namespace:MyApp.Utils"
             Startup="App_OnStartup">